• 22第四章:【07】消息发送重试机制


    一、消息发送重试机制说明

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

    对于消息重投,需要注意以下几点:

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

    二、同步发送失败策略

    对于普通消息,消息发送默认采用 round-robin 策略来选择所发送到的队列。如果发送失败,默认重试 2 次。但在重试时是不会选择上次发送失败的 Broker,而是选择其它 Broker。当然,若只有一个 Broker 其也只能发送到该 Broker,但其会尽量发送到该 Broker 上的其它 Queue。

    // 创建一个producer,参数为Producer Group名称
    DefaultMQProducer producer = new DefaultMQProducer("pg");
    // 指定nameServer地址
    producer.setNamesrvAddr("rocketmqOS:9876");
    // 设置同步发送失败时重试发送的次数,默认为2次
    producer.setRetryTimesWhenSendFailed(3);
    // 设置发送超时时限为5s,默认3s
    producer.setSendMsgTimeout(5000);

    同时,Broker 还具有失败隔离功能,使 Producer 尽量选择未发生过发送失败的 Broker 作为目标 Broker。其可以保证其它消息尽量不发送到问题 Broker,为了提升消息发送效率,降低消息发送耗时。

    思考:让我们自己实现 失败隔离 功能,如何来做?

    1)方案一:Producer 中维护某 JUC 的 Map 集合,其 key 是发生失败的时间戳,value 为 Broker 实例。Producer 中还维护着一个 Set 集合,其中存放着所有未发生发送异常的 Broker 实例。选择目标 Broker 是从该 Set 集合中选择的。再定义一个定时任务,定期从 Map 集合中将长期未发生发送异常的 Broker 清理出去,并添加到 Set 集合。

    2)方案二:为 Producer 中的 Broker 实例添加一个标识,例如是一个 AtomicBoolean 属性。只要该 Broker 上发生过发送异常,就将其置为 true。选择目标 Broker 就是选择该属性值为 false 的 Broker。再定义一个定时任务,定期将 Broker 的该属性置为 false。

    3)方案三:为 Producer 中的 Broker 实例添加一个标识,例如是一个 AtomicLong 属性。只要该 Broker 上发生过发送异常,就使其值增一。选择目标 Broker 就是选择该属性值最小的 Broker。若该值相同,采用轮询方式选择。

    如果超过重试次数,则抛出异常,由 Producer 去保证消息不丢。当然当生产者出现 RemotingException、MQClientException 和 MQBrokerException 时,Producer 会自动重投消息。

    三、 异步发送失败策略

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

    DefaultMQProducer producer = new DefaultMQProducer("pg");
    producer.setNamesrvAddr("rocketmqOS:9876");
    // 指定异步发送失败后不进行重试发送
    producer.setRetryTimesWhenSendAsyncFailed(0)

    四、消息刷盘失败策略

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

  • 相关阅读:
    电子产品使用感受之—我的iPad Pro坏了。。。
    我最近读了什么书?(随时更新)
    我了解到的新知识之--GDPR
    我了解到的新知识之—MPLS
    我了解到的新知识之—Apple Captive Portal 网页认证登陆公共Wifi
    电子产品使用感受之--无线充电器到底是不是鸡肋?
    大家春节好,过节了也不要忘记来听听我的播客节目哦!
    Python学习笔记之--我又开始学习Python了(随时更新)
    电子产品使用感受之--Mac Mini 买了之后有什么用?-- 开发啊!
    第一次个人编程作业
  • 原文地址:https://www.cnblogs.com/niujifei/p/16586484.html
Copyright © 2020-2023  润新知