news 2026/5/26 5:35:46

RocketMQ如何防止消息丢失?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RocketMQ如何防止消息丢失?

文章目录

  • 引言
  • 生产端:确保消息成功发出去
  • 存储端(Broker):确保消息持久化且不丢失
  • 消费端:确保消息处理完再确认
  • 总结

引言

大家好!我们使用消息队列中间件的时候,一般都会涉及到消息丢失怎么兜底的问题。今天我们一起来探讨一下RocketMQ是如何帮我们解决这个问题的,同时这也是面试常问的问题。
作为一个后端开发人员,你肯定知道在分布式系统中,性能数据一致性(可靠性)往往是需要权衡的。RocketMQ 想要实现“消息零丢失”,必须在生产存储消费这三个阶段都进行严格的把控。

生产端:确保消息成功发出去

在发送端,主要通过确认机制重试机制来保证。

  • 使用同步发送 (Sync Send):

    • 机制:生产者发送消息后,会阻塞等待 Broker 的响应。只有收到SEND_OK状态,才算发送成功。
    • 处理:如果收到FLUSH_DISK_TIMEOUTFLUSH_SLAVE_TIMEOUT或者SLAVE_NOT_AVAILABLE,虽然消息可能已经到了 Broker,但持久化或同步可能存在风险。严格场景下,需要根据业务决定是否重试。
    • 代码层:不要使用sendOneway(单向发送,不关心结果),也不要过度依赖sendAsync(除非回调处理极其完善)。
  • 失败重试 (Retry):

    • RocketMQ 客户端默认自带重试机制。如果网络抖动导致发送失败,Producer 会自动重试(默认 2 次)。
    • 你可以配置retryTimesWhenSendFailed
  • 事务消息 (Transactional Message):

    • 场景:解决“本地事务执行成功,但消息发送失败”导致的数据不一致问题。
    • 机制:利用 RocketMQ 的半消息(Half Message)机制,实现类似 2PC(两阶段提交)的效果,确保本地数据库更新消息发送是原子操作。

存储端(Broker):确保消息持久化且不丢失

这是最关键的环节,主要涉及刷盘策略主从复制

  • 刷盘策略:同步刷盘 (SYNC_FLUSH)

    • 默认 (Async):消息写入内存 (PageCache) 即返回成功,由 OS 决定何时写入磁盘。如果机器断电,内存数据会丢失。
    • 零丢失配置:flushDiskType设置为SYNC_FLUSH
    • 效果:消息必须真正写入物理磁盘(CommitLog)后,Broker 才会给 Producer 返回成功。
    • 代价:写入吞吐量会大幅下降。
  • 复制策略:同步复制 (SYNC_MASTER)

    • 默认 (Async):Master 收到消息即可,后台异步同步给 Slave。如果 Master 宕机且磁盘损坏,未同步的消息会丢失。
    • 零丢失配置:brokerRole设置为SYNC_MASTER
    • 效果:Master 收到消息后,必须等待 Slave 也成功写入,才会给 Producer 返回成功。
    • 代价:增加了网络往返延时,可用性略有降低(Slave 挂了可能影响写入)。
  • 高可用架构:DLedger (Raft 协议)

    • RocketMQ 4.5+ 引入了基于 Raft 协议的 DLedger 存储模式。它不仅解决了自动故障切换(Failover),还通过 Raft 的强一致性保证数据不丢失(只要大多数节点存活,数据就在)。

如果不启用Dledger或者同步刷盘(性能下降),我们需要保证异步刷盘和消息不丢失,需要引入本地消息表模式(或称为最大努力通知模式)。
本地消息表的核心思想是:将本地数据库事务消息发送绑定在一起,以确保它们要么同时成功,要么同时失败

在这个模式下,Broker 即使宕机,消息也不会丢失,原因在于:

  1. 保障机制:消息的“生命”已经从 RocketMQ Broker 转移到了生产者的本地数据库中。只要本地事务提交成功,消息就安全了。
  2. 性能提升:Broker 即使是ASYNC_FLUSH异步刷盘,也只影响 Broker 侧的持久化风险,不影响您的业务事务。您将消息记录到本地数据库,这个操作是快速的本地事务,对性能影响小。
  3. 最终一致性:引入一个独立的定时任务:它会定时扫描本地消息表中状态为待发送发送失败的记录,并重新投递给 RocketMQ

消费端:确保消息处理完再确认

消费者端主要防止“消息拿到了,但在业务逻辑处理完之前程序挂了,导致消息被认为已消费”。

  • 手动 ACK 机制 (At-Least-Once):

    • RocketMQ 默认就是“先处理业务,后 ACK”。
    • 关键点:只有当你的业务逻辑(比如写库、调用下游接口)完全执行成功后,才返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS
    • 异常处理:如果业务抛出异常,或者返回RECONSUME_LATER,Broker 会接管该消息,放入重试队列,稍后再次投递。
  • 死信队列 (DLQ):

    • 如果消息重试了 16 次(默认)依然失败,会被放入死信队列,不会被丢弃。你需要建立监控机制,人工介入处理死信队列中的消息。

这里记得处理幂等性问题噢❤️,(如使用数据库唯一键、Redis 去重等),这是实现消息可靠性的另一面硬币。

总结

好的我们从三个方面分层分析了RocketMQ是如何保证消息不丢失的。

对于消息队列的这些消息问题,我们一般都是要从这三方面去考量噢,面试最好也是这样分层次给面试官回答,这样印象分会大大增加❤️

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 0:07:04

EtherCAT 逐帧报文解析:EEPROM 读取与配置阶段

主站采用 APRD(定点读)、APWR(定点写)指令替代广播指令,实现对单个从站的精准操作。1、APRD 定点读机制说明:访问特性:非统一批量读取,为定点访问模式;从站 adp 地址范围…

作者头像 李华
网站建设 2026/5/25 22:28:20

风-储系统仿真模型;通过模糊逻辑控制策略驱动蓄电池变换器运行,以达到为电网提供惯量的目的

风-储系统仿真模型;通过模糊逻辑控制策略驱动蓄电池变换器运行,以达到为电网提供惯量的目的。 可以实现功率平滑输出在能源转型的大背景下,风能作为一种重要的可再生能源,因其清洁、无污染的特点受到广泛关注。然而,风…

作者头像 李华
网站建设 2026/5/25 19:41:40

async/await 的原理

基础问答问:async/await 的原理是什么?答:关键字本身就是 Promise 的语法糖,依托于生成器函数 (Generator) 函数能力实现的。async 关键字标志这个函数为异步函数,并且将返回结果封装为一个 Pro…

作者头像 李华
网站建设 2026/5/25 6:22:13

Flutter 应用保活与后台任务:在 OpenHarmony 上实现定时上报

前言 在 OpenHarmony 生态中,许多应用场景(如健康监测、设备状态上报、位置追踪)要求应用即使在退到后台或屏幕关闭后,仍能周期性执行任务。然而,出于系统资源与电池优化的考虑,OpenHarmony 对后台进程有严…

作者头像 李华
网站建设 2026/5/25 5:50:42

【RL】verl 数据处理

您的 Eurus-2-RL-Data 数据集需要做两个主要适配:文件格式转换和字段映射配置。 快速解决方案 1. 转换文件格式(推荐) 将 arrow 文件转换为 parquet 格式: from datasets import load_dataset import os# 加载原始数据 ds lo…

作者头像 李华