RocketMQ的重试策略

1,563 阅读3分钟

这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

前言

上一篇,我从一个数据重复的问题,引出RocketMQ会在何时会将同一个消息,重复发送。那么,本文将详细聊一聊RocketMQ的重试策略。
TCP协议和HTTP协议的重试机制有所差异,而我们在项目中通过RocketMQ jar提供的api去请求RocketMQ服务,都是TCP协议的,所以本文也将重点放在TCP协议的重试机制上。

消息重试机制

RocketMQ消息收发过程中,若Consumer消费某条消息失败,则RocketMQ会在重试间隔时间后,将消息重新投递给Consumer消费,若达到最大重试次数后消息还没有成功被消费,则消息将被投递至死信队列。
1)重试间隔:消息消费失败后再次被RocketMQ投递给Consumer消费的间隔时间。
2)最大重试次数:消息消费失败后,可被RocketMQ重复投递的最大次数。

那何为死信队列呢?

当一条消息初次消费失败,RocketMQ会自动进行消息重试,达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息。此时,RocketMQ不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。
在RocketMQ中,这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。

重试间隔

RocketMQ并不会在消息消费失败之后就立马再次发送消息,这样设计其实挺符合实际情况了,当客户端挂了,短时间内恢复的可能性不大,而如果是网络波动导致,则有可能立马就恢复了。所以RocketMQ在设计重试间隔时,考虑到这些,就会发现重试间隔会随着重试次数,逐渐增大。下面给出RocketMQ默认前16次的重试间隔,而超过16次之后就是固定2小时发一次了。

第几次重试与上次重试的间隔时间第几次重试与上次重试的间隔时间
110秒97分钟
230秒108分钟
31分钟119分钟
42分钟1210分钟
53分钟1320分钟
64分钟1430分钟
75分钟151小时
86分钟162小时

我们也可以通过MaxReconsumeTimes参数来设置重试次数。

顺序消息

上面说的重试间隔和重试次数是针对无序消息的。而顺序消息,因为是严格按照先进先出(FIFO)的原则进行消息发布和消费,即先发布的消息先消费,后发布的消息后消费。如果还是按照无序消息的重试间隔策略,那么顺序消息将很容易就因一个消息无法消费,导致整个队列积压。
所以顺序消息的重试间隔和重试次数的配置就需要结合业务进行合理的配置才行。
间隔时间可通过自定义参数suspendTimeMillis取值进行配置。参数取值范围:10~30000,单位:毫秒,默认值:1000毫秒,即1秒。
最大重试次数可通过自定义参数MaxReconsumeTimes取值进行配置。该参数取值无最大限制。若未设置参数值,默认最大重试次数为Integer.MAX。