一、重复消费的三种场景
1.发送消息时重复
当一条消息已被成功发送到服务端并完成持久化,此时出现了网络闪断或者客户端宕机,导致服务端对客户端应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条内容相同并且Message ID也相同的消息
2.投递时消息重复
①消息消费的场景下,消息已投递到消费者并完成业务处理,当客户端给服务端反馈应答的时候网络闪断。为了保证消息至少被消费一次,消息队列RocketMQ版的服务端将在网络恢复后再次尝试投递之前已被处理过的消息,消费者后续会收到两条内容相同并且Message ID也相同的消息
②举例
举例来说,假设有一个名为 "order" 的主题(Topic),其中包含订单消息。有两个消费者 A 和 B 订阅了这个主题,并且设置为同一消费组(Consumer Group)。当新的订单消息到达时,RocketMQ 会将消息平均分配到两个消费者的消息队列中,让它们分别处理。但是如果消费者 A 处理消息的速度较慢,而消费者 B 处理消息的速度较快,这时就可能出现以下情况:
- 消息被消费者 B 先消费。
- 消息被消费者 A 后消费。
如果消费者 B 处理消息后出现了某种错误导致消息未被正确处理或者消费者 B 重启了消费端程序,此时 RocketMQ 会将未被确认消费的消息重新投递给消费组内的其他消费者,这时消费者 A 可能会重新消费之前已经被消费过的消息,导致消息的重复消费。
3.负载均衡时消息重复
①(包括但不限于网络抖动、Broker重启以及消费者应用重启)当消息队列RocketMQ版的Broker或客户端重启、扩容或缩容时,会触发Rebalance,此时消费者可能会收到重复消息。
②举例
- 1.假设一个主题中包含订单消息,有两个消费者订阅了该主题并且属于同一个消费组。
- 2.假设有4个队列,刚开始只有一个消费者C1,C1对应4个队列,此时消息已经投递给C1,但C1正在处理,这时候C2进来扩容,需要重新负载均衡,此时C2会抢夺C1的两条队列。
- 3.在负载均衡过程中,RocketMQ 可能会将某个消息队列重新分配给消费者C2,如果此时消息队列中仍有未被确认消费的消息,那么该消息就会被消费者 C2 重复消费,从而导致消息重复。
二、幂等性(当消息重复时,结果是相同的)
1.举例
- 1.Get操作是幂等的
- 2.Post操作通常会添加新的资源,因此是不幂等的
- 3.Put操作如果是set name = nameA是幂等的,
- 如果是set balance = balnace + 100是非幂等的
- 4.Delete根据业务确定,比如如果是删除不存在的数据则是相同的;删除存在的数据,第一次是删除掉了,后面的多次是并没有删除成功的
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。