一、消息的消费重试机制
Producer对发送失败的消息进行重新发送的机制。
采用同步或异步会重试,oneway消息发送方式发送失败没有重试机制。
消息发送重试三种策略:
- 同步发送失败策略
对于普通消息,消息发送默认采用round-robin策略来选择所发送到的队列。如果发送失败,默认重试2次,但在重试时是不会选择上次发送失败的Broker,而是选择其他的Broker。
同时,Broker还具有失败隔离功能,使Producer尽量选择未发生过发送失败的Broker作为目标Broker。
如果超过重试次数,则抛出异常,由Producer去保证消息不丢。当然当生产者出现RemotingException、MQClientException和MQBrokerException时,Producer会自动重投消息。 - 异步发送失败策略
异步发送失败重试时,异步重试不会选择其他broker,仅在同一个broker上做重试,所以该策略无法保证消息不丢。 - 消息刷盘失败策略
消息刷盘超时或是slave不可用(slave同步数据时向master返回状态非SEND_OK)时,默认是不会将消息尝试发送到其他Broker的。不过,对于重要消息可以通过在Broker的配置文件设置retryAnotherBrokerWhenNotStoreOK属性为true来开启。
二、消息消费重试机制
- 顺序消息的消费重试
对于顺序消息,当Consumer消费消息失败后,为了保证消息的顺序性,其会自动不断地进行消息重试,直到消费成功。重试期间应用会出现消息消费被阻塞的情况。对于顺序消息的重试是无休止的,不间断的,直至消费成功,所以,对于顺序消息的消费,务必要保证应用能够及时监控并处理消费失败的情况,避免消费被永久性阻塞。
顺序消息没有发送失败重试机制,但是有消费失败重试。 - 无序消息(普通消息、延时消息、事务消息)的消费重试
当Consumer消费消息失败时,可以通过设置返回状态达到消息重试的效果。无序消息的重试只对集群消费方式生效,广播方式不提供失败重试特性,一个消费失败还有其他消费者进行消费。
对于修改过的重试次数,若修改值小于16,则按照指定间隔进行重试,若大于16的重试时间间隔均为2小时。对于Consumer Group只修改一个,则会应用到所有的其他Consumer实例。多个都修改,采用覆盖采取最后一个修改 的值。若消息还失败,将投入到死信队列。 - 重试队列:存储所有需要重试消费的消息的特殊topic队列。针对消息组的,不是topic,一个topic的消息可以让多个消费者组消费,所以会为这些消费者组各创建一个重试队列。
- 消费重试配置方式:集群消费方式下,消息消费失败后若希望消费重试,则需要在消息监听器接口实现明确的返回值:
方式1:返回ConsumeConcurrentlyStatus.RECONSUME_LATER(官方推荐)
方式2:返回NULL
方式3:抛出异常
- 消息不重试配置方式:ConsumeConcurrentlyStatus.CONSUME_SUCCESS
三、死信队列
当一条消息消费重试达到最大重试次数后仍然消费失败,此时队列将消息扔到特殊的队列中,这个队列就是死信队列。
- 特征:死信队列中消息消费者看不到消息,无法再次消费;死信队列中消息和正常消息有效期一样(Commitlog文件中设置3天);死信队列就是一个特殊的Topic,名称为%DLQ%consumerGroup@ consumerGroup;如果一个消费者组未产生死信消息,则不会为其创建相应的死信队列。
- 死信消息的实际处理:
实际上,当一条消息进入死信队列意味着系统出现某些问题,代码存在bug。对于死信消息手工处理。