消息队列RocketMQ入门实践-消息重试策略(六)

本文详细介绍了RocketMQ的消息重试机制,包括Producer端的3次内部重试和Consumer端的自动与手动重试策略,并探讨了消息重复的解决方案,建议在业务层面实现幂等性处理或使用日志记录已处理消息ID来避免重复消费。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

消息队列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 客户端内部做,而是要求应用自己去完成,是基于以下几点考虑:

  1. MQ 的客户端设计为无状态模式,方便任意的水平扩展,且对机器资源的消耗仅仅是 cpu、内存、网络。
  2. 如果 MQ 客户端内部集成一个 KV 存储模块,那举数据只有同步落盘才能较可靠,而同步落盘本身性能开销较大,所以通常会采用异步落盘,又由于应用关闭过程不受 MQ 运维人员控制,可能经常会发生 kill -9 返样暴力方式关闭,造成数据没有及时落盘而丢失。
  3. Producer 所在机器的可靠性较低,一般为虚拟机,不适合存储重要数据。

综上,建议重试过程交由应用来控制。

二、consumer端重试

消费者端的失败,分为2种情况,一种是exception,一种是timeout。

1.exception

消息正常的到了消费者,结果消费者发生异常,处理失败了。例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。

消息的状态:

### RocketMQ 消息队列实战使用教程 #### 1. 创建生产者并发送消息RocketMQ 中,可以通过 `DefaultMQProducer` 类来创建一个生产者实例,并设置其名称服务器地址以及指定的主题(Topic)。以下是创建生产者的代码示例: ```java import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.common.message.Message; public class Producer { public static void main(String[] args) throws Exception { // 创建生产者实例并指定生产者组名 DefaultMQProducer producer = new DefaultMQProducer("YourProducerGroup"); // 设置 NameServer 地址 producer.setNamesrvAddr("localhost:9876"); // 启动生产者 producer.start(); // 构造消息对象 Message message = new Message("YourTopic", "TagA", ("Hello RocketMQ").getBytes()); // 发送同步消息 producer.send(message); // 关闭生产者 producer.shutdown(); } } ``` 上述代码展示了如何通过 Java API 来实现一条简单消息的发送操作[^1]。 --- #### 2. 创建消费者并接收消息 为了消费来自主题的消息,可以利用 `DefaultMQPushConsumer` 类构建消费者实例。下面是一个完整的消费者配置与监听逻辑的例子: ```java import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; public class Consumer { public static void main(String[] args) throws MQClientException { // 初始化消费者实例 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("YourConsumerGroup"); // 配置 NameServer 地址 consumer.setNamesrvAddr("localhost:9876"); // 订阅特定主题下的标签 consumer.subscribe("YourTopic", "*"); // 注册消息监听器 consumer.registerMessageListener((msgs, context) -> { msgs.forEach(msg -> System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()))); // 返回成功状态 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }); // 开启消费者服务 consumer.start(); } } ``` 此部分实现了基本的消息订阅功能,并设置了回调函数处理接收到的数据流[^2]。 --- #### 3. 幂等性保障机制 由于分布式环境下可能存在重复投递的情况,在设计业务逻辑时需考虑消费端是否具备幂等功能。例如更新数据库记录或者累加计数器场景下应避免因重试而导致数据异常变化。具体做法如下所示: - **唯一标识符**:每条消息附加唯一的 ID 字段; - **去重表/缓存层校验**:首次执行写入动作前先查询目标资源是否存在相同键值项;如果存在则跳过后续流程直接返回成功响应。 这种策略能够有效减少不必要的计算开销同时提高系统的可靠性水平[^3]。 --- #### 4. 主题管理界面操作指南 对于初学者来说除了编码之外还需要熟悉运维方面的知识比如新增自定义 topic 。一般情况下我们可以在 web 控制台上完成此类任务而无需修改底层程序文件结构。步骤描述如下: 1. 登录到 RocketMQ 管理后台找到左侧菜单中的 “Topic 管理” 菜单项。 2. 切换至对应集群分区后点击顶部按钮触发新建对话框填写必要参数提交保存即可生效[^4]。 以上就是关于 rocket mq 基础入门级应用开发指导文档希望对你有所帮助! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java升级之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值