Rabbitmq之消息重排序分析

一、场景描述

rabbitmq经常会用到一个参数requeue,消费者在返回Nack时通过设置requeue=true,确保消息重新排队后继续被消费。

疑问:消息requeue底层是怎么实现的,猜测是以下两种情况之一:

1、消费者(Consumer)从本地队列中删除该消息并通知Rabbitmq将该消息从Broker维护的队列头部取出放到队列尾部?

2、消费者(Consumer)只是将该消息重新放到本地维护的队列尾部,Rabbitmq服务端队列无须任何操作?

带着以上两个问题,我们先通过一个简单的demo来验证一下

二、过程分析

测试的Demo代码是这样约定的:

数字0:消费者返回ACK,消费成功

数字1:首次消费1时模拟异常返回Nack,同时设置Requeue=true,第二次消费1时返回ACK

数字2:首次消费2时模拟异常返回Nack,同时设置Requeue=true,第二次消费2时返回ACK

数字3:消费者返回ACK,消费成功

数字4:消费者返回ACK,消费成功

通过代码debug,消费过程的示意图如下(基中标蓝色的是Unacked状态的message):

1、消费者暂且设置qos=5,即broker会向消费者一次性投递5条消息

2、Consumer消费完0后返回ACK,Broker会删除对应的消息0

3、继续消费1时,消费者发生了异常并且捕获异常后返回了Nack,且requeue=true


 我们可以看到,消费者消息消费失败后尝试重新排队,此时消息1回到了消费者本地队列的尾部

4、继续消费2时,消费者发生了异常并且捕获异常后返回Nack,且requeue=true


 此时消息2回到了本地队列的尾部

5、继续消费3后返回Ack,Consumer队列中的消息3被删除,其中Broker中的消息3被标记为'待删除',但还留在队列中,等待消息1、2依次出队列后被删除 

6、继续消费4后返回Ack,Consumer队列中的消息4被删除,其中Broker中的消息4被标记为'待删除',但还留在队列中,等待消息1、2、3依次出队列后被删除 

最终消费端 消费消息 的顺序打印如下:0 -> 3 -> 4  -> 1 -> 2

注意:如果本地队列中存在未消费完的消息(Unacked),那么RabbitMQ服务端不会继续投递消息

三、总结

返回Nack且requeue为true时,重新排队是在消费者端完成的,对Broker中的队列和消息没有影响

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值