当前位置:   article > 正文

RocketMq(二)消息重试机制_rocketmq消息重试

rocketmq消息重试

一、消息发送重试机制:

Producer对发送失败的消息进行重新发送的机制,称为消息发送重试机制,也称为消息重投机制。

  1. 生产者在发送消息时,若采用同步或异步发送方式,发送失败会重试,但oneway消息发送方式发送失败是没有重试机制的。
  2. 只有普通消息具有发送重试机制,顺序消息是没有的。
  3. 消息重投机制可以保证消息尽可能发送成功、不丢失,但可能会造成消息重复。消息重复在RocketMQ中是无法避免的问题。
  4. 消息重复在一般情况下不会发生,当出现消息量大、网络抖动,消息重复就会成为大概率事件。
  5. producer主动重发、consumer负载变化(发生Rebalance,不会导致消息重复,但可能出现重复消费)也会导致重复消息。
  6. 消息重复无法避免,但要避免消息的重复消费。
  7. 避免消息重复消费的解决方案是,为消息添加唯一标识(例如消息key),使消费者对消息进行消费判断来避免重复消费。
  8. 消息发送重试有三种策略可以选择:同步发送失败策略、异步发送失败策略、消息刷盘失败策略。

1、同步发送失败策略:对于普通消息,消息发送默认采用round-robin策略来选择所发送到的队列。如果发送失败,默认重试2次。但在重试时是不会选择上次发送失败的Broker,而是选择其它Broker。当然,若只有一个Broker其也只能发送到该Broker,但其会尽量发送到该Broker上的其它Queue。同时,Broker还具有失败隔离功能,使Producer尽量选择未发生过发送失败的Broker作为目标Broker。其可以保证其它消息尽量不发送到问题Broker,为了提升消息发送效率,降低消息发送耗时。如果超过重试次数,则抛出异常,由Producer去保证消息不丢。当然当生产者出现RemotingException、MQClientException和MQBrokerException时,Producer会自动重投消息。

2、异步发送失败策略:异步发送失败重试时,异步重试不会选择其他broker,仅在同一个broker上做重试,所以该策略无法保证消息不丢。

3、消息刷盘失败策略:消息刷盘超时(Master或Slave)或slave不可用(slave在做数据同步时向master返回状态不是SEND_OK)时,默认是不会将消息尝试发送到其他Broker的。不过,对于重要消息可以通过在Broker的配置文件设置retryAnotherBrokerWhenNotStoreOK属性为true来开启。

二、消息消费重试机制:

1、顺序消息:对于顺序消息,当Consumer消费消息失败后,为了保证消息的顺序性,其会自动不断地进行消息重试,直到消费成功。消费重试默认间隔时间为1000毫秒。重试期间应用会出现消息消费被阻塞的情况。由于对顺序消息的重试是无休止的,**不间断的,直至消费成功,所以对于顺序消息的消费,**务必要保证应用能够及时监控并处理消费失败的情况,避免消费被永久性阻塞。注意,顺序消息没有发送失败重试机制,但具有消费失败重试机制。

2、无序消息:对于无序消息(普通消息、延时消息、事务消息),当Consumer消费消息失败时,可以通过设置返回状态达到消息重试的效果。不过需要注意,无序消息的重试只对集群消费方式生效,广播消费方式不提供失败重试特性。即对于广播消费,消费失败后,失败消息不再重试,继续消费后续消息。对于无序消息集群消费下的重试消费,每条消息默认最多重试16次,但每次重试的间隔时间是不同的,会逐渐变长。每次重试的间隔时间如下表。若一条消息在一直消费失败的前提下,将会在正常消费后的第4小时46分后进行第16次重试。 若仍然失败,则将消息投递到死信队列。

重试次数与上次重试的间隔时间重试次数与上次重试的间隔时间
110秒97分钟
230秒108分钟
31分钟119分钟
42分钟1210分钟
53分钟1320分钟
64分钟1430分钟
75分钟151小时
86分钟162小时
  1. DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg");
  2. // 修改消费重试次数
  3. consumer.setMaxReconsumeTimes(10);

对于修改过的重试次数,将按照以下策略执行

  1. 若修改值小于16,则按照指定间隔进行重试。
  2. 若修改值大于16,则超过16次的重试时间间隔均为2小时。

对于Consumer Group,若仅修改了一个Consumer的消费重试次数,则会应用到该Group中所有 其它Consumer实例。若出现多个Consumer均做了修改的情况,则采用覆盖方式生效。即最后被 修改的值会覆盖前面设置的值。

三、重试队列:

对于需要重试消费的消息,并不是Consumer在等待了指定时长后再次去拉取原来的消息进行消费,而是将这些需要重试消费的消息放入到了一个特殊Topic的队列中,而后进行再次消费的。这个特殊的队列就是重试队列。当出现需要进行重试消费的消息时,Broker会为每个消费组都设置一个Topic名称 为%RETRY%consumerGroup@consumerGroup 的重试队列。注意:

1)这个重试队列是针对消息才组的,而不是针对每个Topic设置的(一个Topic的消息可以让多 个消费者组进行消费,所以会为这些消费者组各创建一个重试队列)。
2)只有当出现需要进行重试消费的消息时,才会为该消费者组创建重试队列。

注意,消费重试的时间间隔与延时消费的延时等级十分相似,除了没有延时等级的前两个时间 外,其它的时间都是相同的。Broker对于重试消息的处理是通过延时消息实现的。先将消息保存到SCHEDULE_TOPIC_XXXX延迟队列中,延迟时间到后,会将消息投递到%RETRY%consumerGroup@consumerGroup重试队列中。

消息重试配置方式:集群消费方式下,消息消费失败后若希望消费重试,则需要在消息监听器接口的实现中明确进行如下三种方式之一的配置

  1. 方式1:返回ConsumeConcurrentlyStatus.RECONSUME_LATER(推荐)
  2. 方式2:返回Null
  3. 方式3:抛出异常

集群消费方式下,消息消费失败后若不希望消费重试,则在捕获到异常后同样也返回与消费成功后的相同的结果,即ConsumeConcurrentlyStatus.CONSUME_SUCCESS,则不进行消费重试。

四、死信队列:

1、定义:当一条消息初次消费失败,消息队列会自动进行消费重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。这个队列就是死信队列(Dead-Letter Queue,DLQ),而其中的消息则称为死信消息(Dead-Letter Message,DLM)。死信队列是用于处理无法被正常消费的消息的。实际上,当⼀条消息进入死信队列,就意味着系统中某些地方出现了问题,从而导致消费者无法正常消费该消息,比如代码中原本就存在Bug。因此,对于死信消息,通常需要开发人员进行特殊处理。最关键的步骤是要排查可疑因素,解决代码中可能存在的Bug,然后再将原来的死信消息再次进行投递消费。

2、特征:

(1)死信队列中的消息不会再被消费者正常消费,即DLQ对于消费者是不可见的。
(2)死信存储有效期与正常消息相同,均为3天(commitlog文件的过期时间),3天后会被自动删除。
(3)死信队列就是一个特殊的Topic,名称为%DLQ%consumerGroup@consumerGroup ,即每个消费者组都有一个死信队列。
如果⼀个消费者组未产生死信消息,则不会为其创建相应的死信队列。
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/603847
推荐阅读
相关标签
  

闽ICP备14008679号