RocketMQ无法避免消息重复,原因主要有以下几点:
-
签收的偏移量是定时(每5秒/次)同步到服务端的。
-
为保证消息不丢失,SDK每次提交的总是队列未签收的最小偏移量(比如无序消费,offset为1,2,3,4,5 的消息,1,3,4,5消费并已签收,2未签收,签收时最后提交的偏移量将会是2,如果此时,客户端重启,会从2这个位置开始消费)。
-
有网络交互就不能确保每一次的交互数据都是送达的,为保证数据不丢失就要进行重试,有重试就存在重复的可能。
如果业务对消费重复非常敏感,务必要注意,建议可以采用以下两种方式处理:
- 业务层面做去重处理,可以根据msgId;如果key字段为业务唯一字段,也可采用key去重。
- 业务逻辑实现消费幂等,即多次处理同一消息,对业务的影响是幂等的。