zl程序教程

您现在的位置是:首页 >  Python

当前栏目

RabbitMQ重复消费

2023-04-18 16:14:40 时间

1、重复消费的原因

1)多个消费者,其中一个消费信息后没有通知队列(没有给mq发ack,或者给mq发ack的过程中挂了、失败了),队列又把消息发给了其他消费者就会重复消费。

2)对于非幂等性操作,要防止重复消费;
对于幂等性操作一般不用防止重复消费。
多次操作,得到的结果相同,就是幂等性操作;比如,查询属于幂等性操作,新增、更新属于非幂等性操作。

2、解决方法

用redis。
在消费者收到消息时,先执行setnx,setnx是redis命令,是’SET if Not eXists’(如果不存在,则 SET)的简写,RedisTemplate中也有对应的方法。setnx执行后,如果返回true说明key不存在、设置成功,如果返回false说明key已存在、设置失败。

eg:我们约定
id=0,表示正在执行
id=1,表示执行成功

消费者收到消息,在执行业务前,先用setnx方法试着将id放入redis中,

Boolen result = redisTemplate.opsForValue().setIfAbsent(orderId+"_reineforce", "0");

1)如果key不存在,即setnx返回true,消费者就正常消费;
2)如果key存在,即setnx返回false,那么就要取出key的值作判断,
为0就不消费;
为1就说明该消息其他消费者已经消费过了,只是发ack没成功,这里直接ack就行。

极端情况
第一个消费者正在执行业务时,挂了、出现死锁,这种怎么办?
在setnx的基础上,再给key设置一个生存时间,防止出现死锁。