持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
万一消息处理失败了可以走重试队列吗?
RocketMQ有消息失败重试机制。即消息消费ack返回RECONSUME_LATER状态,然后broker会过一会儿自动给我们重试。那这个方案可以用在顺序消息的场景中吗?
答案是肯定不行。因为如果你的consumer获取到订单的一个insert binlog,结果处理失败了,此时返回了RECONSUME_LATER,那 么这条消息会进入重试队列,过一会儿才会交给你重试。但是此时broker会直接把下一条消息,也就是这个订单的update binlog交给你来处理,此时万一你执行成功了,就根本没有数据可以更新!又会出现消息乱序的问题。
解决办法
对于有序消息的方案中,如果你遇到消息处理失败的场景,就必须返回SUSPEND_CURRENT_QUEUE_A_MOMENT这个状态,意思是先等一会儿,一会儿再继续处理这批消息,而不能把这批消息都放入重试队列里去,然后直接处理下一批消息。
总结
如果你一定要求消息是有序的,那么必须得用上述的有序消息方案,同时对这个方案,如果你要确保消息不丢失,那么可以和消息零丢失方案(从生产端、服务端、消费端来保证)结合起来,如果你要避免消息重复处理,还需要在消费者那里处理消息的时候,去看一下,消息如果已经存在就不能重复插入也就是消息幂等,等等。 同时还需要设计自己的消息处理失败的方案,也就是不能进入重试队列,而是暂停等待一会儿,继续处理这批消息。