系列文章目录
消息队列RocketMQ入门实践(一)
消息队列RocketMQ入门实践(二)
消息队列RocketMQ入门实践–关键特性(三)
消息队列RocketMQ入门实践–关键特性(四)
消息队列RocketMQ入门实践–消息存储(五)
前言
在消息的发送和消费过程中,都有可能出现错误,如网络异常等,出现了错误就需要进行错误重试,这种消息的重试需要分2种,分别是producer端重试和consumer端重试。
今天这篇文章就来聊一聊RocketMQ是如何进行消息重试策略的。
一、producer端重试
生产者端的消息失败,也就是Producer往MQ上发消息没有发送成功,比如网络抖动导致生产者发送消息到MQ失败。
Producer 的 send 方法本身支持内部重试,重试逻辑如下:
- (1)至多重试 3 次。
- (2) 如果发送失败,则轮转到下一个 Broker。
- (2)返个方法的总耗时时间不超过 sendMsgTimeout 设置的值,默认10s。
所以,如果本身往 broker 发送消息产生超时异常,就不会再做重试。
以上策略仍然不能保证消息一定发送成功,为保证消息一定成功,建议应用返样做:如果调用 send 同步方法发送失败,则尝试将消息存储到 db,由后台线程定时重试,保证消息一定到达 Broker。
上述 db 重试方式为什么没有集成到 MQ 客户端内部做,而是要求应用自己去完成,是基于以下几点考虑:
- MQ 的客户端设计为无状态模式,方便任意的水平扩展,且对机器资源的消耗仅仅是 cpu、内存、网络。
- 如果 MQ 客户端内部集成一个 KV 存储模块,那举数据只有同步落盘才能较可靠,而同步落盘本身性能开销较大,所以通常会采用异步落盘,又由于应用关闭过程不受 MQ 运维人员控制,可能经常会发生 kill -9 返样暴力方式关闭,造成数据没有及时落盘而丢失。
- Producer 所在机器的可靠性较低,一般为虚拟机,不适合存储重要数据。
综上,建议重试过程交由应用来控制。
二、consumer端重试
消费者端的失败,分为2种情况,一种是exception,一种是timeout。
1.exception
消息正常的到了消费者,结果消费者发生异常,处理失败了。例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。
消息的状态: