背景
为什么会出现这种问题呢?还得从rmq的消息投递和消费说起,下面给出一个例子
生产消费流程
1:生成者投递消息到broker
2:broker接受到消息并ack
3:消费者从broker中push/pull消息
4:3步骤完事后回复broker ——》 ACK
导致原因
对于上述的完成流程,只要破坏其中的ack流程就会导致消息重复发送或重新消费,以下列出部分
破坏条件 | 影响 | 案例 |
---|---|---|
破坏broker给生产者的ack | 生产者可能会重复发送 | broker负载高,延迟大,突然不在线等 |
破坏消费者给broker的ack | 消费者可能会重复消费 | 在ack回复的时候,broker觉得自己ack超时了等原因 |
........... | ........... | ........... |
分析
我们只要控制好每条消息只是消费一次就ok了,那么消息的幂等处理就来了,根据消费者部署拓扑分如下几种情况
部署拓扑 | 解决办法 | 备注 |
---|---|---|
单点 | 可以使用 synchronized + 业务check | |
集群 | 考虑使用高性能的 分布式锁 + 业务check |
单点模型
流程如下
消息进到消费者中,肯定是顺序进入的,只要保证这个处理消息的方法处理业务逻辑是顺序的,主要还是在于数据的处理问题,需要在厨业具体业务逻辑的时候,判断这条消息是否消费过,如果没有消费过,直接消费就好,如果消费了,直接丢弃,回复一个OK
集群模型
流程如下
消息分别进入到消费者1和消费者2中,不巧的是,这时候两个jvm都会去查数据库之类的check状态,发现都是合法,就会继续下面的操作,导致消息多次消费。而是有了下面的流程
改进流程
扩展
分布式锁:目前市面上有几种常见的分布式解决方案
方案 | 备注 |
---|---|
mysql | |
Zookeeper | |
Redis | |
.... |
参考
分布式锁常见解决方案
https://blog.csdn.net/weixin_45191798/article/details/103115152?spm=1001.2014.3001.5501
总结
1、本篇从引入为什么会有消息重复消费,原因,以及基本的杜绝原理
2、扩展了分布式锁常见的几种解决方案