关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?

Posted 奔跑中的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?相关的知识,希望对你有一定的参考价值。

消息的投递方式

我们说,在消息系统中,有多种可能的消息投递保证:

1、  最多一次。消息可能会丢失,但是不会重复。

2、  至少一次。消息不会丢失,但是会造成重复。

3、  有且只有一次。这是大家想得到的,但是看下面我的分析,你会发现真的很难。

 

问题

假设我们的broker能保证在server端只有一条消息,那么在消费的过程中,可能会发生下面的问题:


也就是说,第2步已经成功了,但是第3步返回结果的时候失败了,这时候只能重试一次,相当于又做了一次count-1

 

所以,即便是在broker端消息做到了唯一,消费的过程也是无法保证的。虽然ActiveMQ所做的broker端唯一,意义显得并不像想象中那么重要了。这个理由被无数的初学者当成拒绝kafka的理由显然是非常愚蠢的。

 

这个问题不只是在MQ这个场景中,在很多要求强一致性的场景显然是被忽略了,下面举个例子。

 

分布式锁安全吗?

无论你使用redis,还是redlock,或者是zookeeper,都无法保证。如上图所示。这个问题曾经在redis作者antirezMartinKleppmann的论战中被体现出来过。这个具体内容找时间另写一篇。

 

到底有没有解决方法?

1、就是把offset和业务处理放到一个库中,作为一个单库事务处理。保证唯一性。

2、  表做到幂等,如果如上图所示需要减一的操作,可以增加一张流水表,单库事务保证。

 

根据场景定义

如果需要强一致,需要考虑如上方案,但是并不是所有的场景都有这个要求,可以根据实际情况定义,如果要求不高,完全可以在数据库操作前通过缓存过滤一下。这样可以达到broker唯一的目的,但是上图的问题仍然解决不了,因为发生的概率比较小(如果概率高,相信早就有相应的解决方案了),如果能容忍,可以选择忽略。

 

 


以上是关于关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?的主要内容,如果未能解决你的问题,请参考以下文章

mq探索--什么是分布式事务CAP

架构之路(分布式三部曲)--WS+MQ+WCF+EF(Code First)

4redis 分布式锁

阿里面试:说说你项目里使用的 MQ ,分布式系统中 MQ 作用?

关于消息队列的技术选型

关于MQ的几件小事如果让你设计一个MQ,你怎么设计