关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?
Posted 奔跑中的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?相关的知识,希望对你有一定的参考价值。
消息的投递方式
我们说,在消息系统中,有多种可能的消息投递保证:
1、 最多一次。消息可能会丢失,但是不会重复。
2、 至少一次。消息不会丢失,但是会造成重复。
3、 有且只有一次。这是大家想得到的,但是看下面我的分析,你会发现真的很难。
问题
假设我们的broker能保证在server端只有一条消息,那么在消费的过程中,可能会发生下面的问题:
也就是说,第2步已经成功了,但是第3步返回结果的时候失败了,这时候只能重试一次,相当于又做了一次count-1。
所以,即便是在broker端消息做到了唯一,消费的过程也是无法保证的。虽然ActiveMQ所做的broker端唯一,意义显得并不像想象中那么重要了。这个理由被无数的初学者当成拒绝kafka的理由显然是非常愚蠢的。
这个问题不只是在MQ这个场景中,在很多要求强一致性的场景显然是被忽略了,下面举个例子。
分布式锁安全吗?
无论你使用redis,还是redlock,或者是zookeeper,都无法保证。如上图所示。这个问题曾经在redis作者antirez和MartinKleppmann的论战中被体现出来过。这个具体内容找时间另写一篇。
到底有没有解决方法?
1、就是把offset和业务处理放到一个库中,作为一个单库事务处理。保证唯一性。
2、 表做到幂等,如果如上图所示需要减一的操作,可以增加一张流水表,单库事务保证。
根据场景定义
如果需要强一致,需要考虑如上方案,但是并不是所有的场景都有这个要求,可以根据实际情况定义,如果要求不高,完全可以在数据库操作前通过缓存过滤一下。这样可以达到broker唯一的目的,但是上图的问题仍然解决不了,因为发生的概率比较小(如果概率高,相信早就有相应的解决方案了),如果能容忍,可以选择忽略。
以上是关于关于MQ中的“有且只消费一次”误导了很多人。分布式锁安全吗?的主要内容,如果未能解决你的问题,请参考以下文章
架构之路(分布式三部曲)--WS+MQ+WCF+EF(Code First)