RocketMQ 如何保证全链路消息不丢失?

目录

1. RocketMQ 消息丢失的原因有哪些

2. 如何保证 RocketMQ 全链路消息不丢失

2.1 保证生产者发送消息到 MQ,消息不丢失

2.2 保证消息写入 Broker 后不丢失

2.3 保证 Broker 集群时,消息不丢失

2.4 保证消费者消费消息不丢失

3. 如果整个 MQ 服务都挂了呢,怎么保证消息零丢失


1. RocketMQ 消息丢失的原因有哪些

​所有 MQ 产品消息丢失的元凶无非就两个:网络+缓存

这两个原因落地到具体的场景:

1.生产者发送消息到 MQ,消息丢失

2.消息写入 MQ,消息丢失

    ① 消息写入内存后非正常关机;

    ② 消息写入磁盘后,磁盘坏了;

    ③ master 数据备份到 slave 由于网络原因导致备份失败;

3.消息者消费 MQ ,消息丢失

2. 如何保证 RocketMQ 全链路消息不丢失

2.1 保证生产者发送消息到 MQ,消息不丢失

【方案一】同步发送 + 消息重试机制

Producer 发送消息的三种方式:

1.单向发送:消息发送出去就不管了.

2.同步发送: 同步等待 Broker 响应.

3.异步发送: 异步处理 Broker 通知.

同步发送+消息重试:生产者向 mq 发送消息,mq 收到消息成功就会回复 ack,如果生产者没收到 ack,就会重试再次发送消息到 mq,通过这种机制来保证消息不丢失。(重试的消息会被加入到重试队列中,重试一定次数还未成功发送就会被加入到死信队列中)

PS:同步发送有个缺点,生产者在等待服务端回复ack的过程,他干不了别的事,所以比较综合的方式就是采用异步发送的方式,异步发送它会注册一个 sendCallback 回调监听器,相当于找了个小弟给你干活,可以在小弟的这个回调方法里面写逻辑,如果消息发送失败了,让小弟去重试就行。

【方案二】RocketMQ 的事务消息机制

⭐ RocketMQ 事务消息机制的思想:

        首先,事务消息的本质就是,生产者这边处理一个本地事务,消费者这边处理一个本地事务,这两个事务要保证一个原子性,但这是一个分布式事务,直接保证这两个事务的一致性很难做到; 而 RocketMQ 的事务机制是怎么保证这两个本地事务的一致性的呢,它是通过保证生产者处理本地事务和往 RocketMQ 发消息这两个操作是原子性的,然后在消费者这一端,只要生产者消息成功发送到了 MQ,MQ 就可以通过重试的机制将消息发送给消费者,哪怕当时消费者的事务处理失败了,那么经过多次的重试,最终消费的事务也会执行成功。所以他的本质是通过保证事务消息的一半,从而来保证整体业务逻辑的事务性

⭐ RocketMQ 事务消息机制的执行流程:

【参照上图】

1.生产者向 MQ 发送半消息(half)&#

### RocketMQ 消息可靠性的配置与最佳实践 #### 1. Broker 部署模式的选择 为了保证消息的可靠性,可以根据实际需求选择不同的Broker角色部署方式。如果对消息可靠性有较高要求,建议采用 `SYNC_MASTER` 加 `SLAVE` 的部署方式。这种方式下,主节点会在写入数据后等待从节点确认复制完成后才返回成功响应给生产者[^3]。 相比之下,`ASYNC_MASTER` 虽然性能更高,但由于其异步刷盘机制可能导致在极端情况下丢失部分未持久化的消息。因此,当优先级放在高可用性和强一致性时,推荐使用同步双写策略。 #### 2. 刷盘类型设置 (FlushDiskType) RocketMQ 提供两种磁盘刷新策略: - **ASYNC_FLUSH**: 异步刷盘,性能较好但存在一定的消息丢失风险。 - **SYNC_FLUSH**: 同步刷盘,虽然吞吐量较低,但在断电或其他意外场景下能最大程度保障数据不丢。 针对需要极高可靠性的业务场景,应选用 `SYNC_FLUSH` 来确保每条消息都被安全存储至硬盘后再反馈 ACK 给客户端。 #### 3. 发送消息的可靠性控制 ##### (1)发送模式选择 RocketMQ 支持多种消息发送模式,其中最可靠的为单向(Oneway)、同步(SyncSend)和异步(AsyncSend)。对于追求最高级别的可靠性而言,应当选取 SyncSend 方式。它会阻塞当前线程直到收到服务器端的成功回复为止;而 AsyncSend 可以提高并发度但也增加了复杂性管理回调函数失败的情况处理逻辑[^4]。 ##### (2)重试机制配置 无论是哪种发送形式都不可避免会出现暂时性错误如网络波动等问题造成投递失败的现象发生。此时可以通过调整 Producer 参数来增强系统的容错能力: ```java DefaultMQProducer producer = new DefaultMQProducer("group_name"); producer.setRetryTimesWhenSendFailed(3); // 设置最大重试次数,默认值为2次 producer.start(); ``` 上述代码片段展示了如何设定当消息初次尝试未能送达目标 Topic Partition 之后允许再次发起最多三次额外的努力去恢复连接恢复正常操作流程。 #### 4. 实现最终一致性解决方案 即使采取了以上措施仍无法完全杜绝所有潜在的风险因素影响整个链路正常运转的可能性。为此引入了一套基于本地事务日志配合补偿机制达成全局范围内的一致状态维护方法论即所谓的“两阶段提交协议”。具体步骤如下所示: - **第一步:** 更新应用内部数据库的同时生成一条待办事项记录存放到关系型DB表里头; - **第二步:** 如果前面的操作顺利完成那么继续推进下一步骤即将该笔交易详情推送到远程Kafka集群上面去通知下游订阅方知晓最新动态变化信息; - **第三步:** 假设因为某些原因导致最后一步没能按时完成则启动定时器周期扫描那些处于悬而未决状态下订单重新触发推送动作直至彻底解决掉遗留下来的历史欠账问题为止。 这种做法有效弥补了单纯依赖单一组件难以克服的技术局限从而构建起更加健壮稳定的应用生态系统环境。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Master_hl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值