RocketMQ整体工作流程_详解

RocketMQ 整体工作流程(端到端)详解:从发消息到消费落库

这篇文档讲清楚 RocketMQ “一条消息从生到死”的全过程:
Producer 怎么找 Broker、Broker 怎么存、Consumer 怎么拉、Offset 怎么提交、失败怎么重试/进 DLQ
你看完应该能把 RocketMQ 的工作流画出来,并且能解释线上常见现象:堆积、重复消费、顺序、事务、延时。


目录


1. 一句话总览:RocketMQ 在干嘛

RocketMQ 做的事可以浓缩成:

Producer 把消息写到 Broker 的 CommitLog(并按 Topic/Queue 建索引),Consumer 从 Broker 按 Offset 拉消息处理,成功就提交 Offset,失败就重试,重试多了进 DLQ。


2. 核心角色与它们的职责

  • NameServer:存路由(Topic → Broker/Queue),无状态,可多节点
  • Broker:接收/存储/投递消息,维护索引、复制、刷盘、重试队列等
  • Producer:发消息,负责重试与选择队列(可自定义路由)
  • Consumer:收消息,负责处理、幂等、Offset、重试/死信处理
  • (可选) Proxy(5.x 常见):接入层,统一协议/鉴权/多语言等

3. 端到端流程总图

(1) Broker 启动 -> 向 NameServer 注册路由/心跳
        |
        v
(2) Producer/Consumer 启动 -> 从 NameServer 拉取路由缓存
        |
        v
(3) Producer send(msg) -> 选择 Topic 的某个 Queue -> 直连 Broker 写入
        |
        v
(4) Broker 存储:CommitLog 顺序写 -> 构建 ConsumeQueue/Index -> 刷盘/复制 -> ACK
        |
        v
(5) Consumer 拉取:根据 (Topic,Queue,Offset) Pull -> Broker 读 ConsumeQueue/CommitLog 返回消息
        |
        v
(6) Consumer 处理业务 -> 成功提交 Offset / 失败进入重试 -> 多次失败进 DLQ
        |
        v
(7) Rebalance:组内实例变化 -> 队列重新分配 -> 消费者接管新队列从 Offset 继续

4. Producer 发送流程(从路由到 ACK)

4.1 启动与路由发现

Producer 启动时做几件事:

  1. 连接/配置多个 NameServer 地址
  2. 拉取 Topic 路由(包含:Topic 有哪些队列、队列在哪些 Broker 上)
  3. 缓存路由,并定期更新

注意:Producer 不会每次发消息都问 NameServer,而是用缓存 + 定时刷新,减少中心依赖。

4.2 选择队列(负载均衡)

Topic 一般有多个队列(MessageQueue)。Producer 发送时会:

  • 默认轮询/随机选择一个队列做负载均衡
  • 也可以按业务键(orderId)自定义选择队列(用于顺序消息)

队列是并行度单位:队列越多,理论并行度越高,但运维成本也越高。

4.3 发送与重试

发送流程(简化):

  1. Producer 把 Message 发给选中的 Broker
  2. 若失败/超时:按策略重试(可能换 Broker/换队列)
  3. 达到重试上限仍失败:返回失败,由业务决定补偿(落库重发等)

生产重点

  • 发送失败不要“吞掉”,必须日志 + 告警 + 补偿方案
  • 核心链路建议“落库+异步重试”做最终保障

4.4 Broker 返回成功到底代表什么

这点必须搞清楚,不然你会误以为“绝对不丢”。

Broker 返回成功通常代表:

  • 消息已经写入 Broker(至少进入内存/PageCache),并满足你的刷盘/复制策略

不同策略的可靠性不同:

  • ASYNC_FLUSH:返回成功时可能还没落盘(极端断电可能丢最后一段)
  • SYNC_FLUSH:返回成功代表已刷盘更稳
  • ASYNC_MASTER:复制可能滞后
  • SYNC_MASTER:主从确认后才成功(更稳)

5. Broker 存储流程(CommitLog → ConsumeQueue → Index)

RocketMQ 高吞吐的核心:顺序写 CommitLog + 索引分层

5.1 CommitLog(顺序写)

Broker 收到消息后:

  1. 进行校验(Topic、权限、大小等)
  2. 追加写入 CommitLog(append-only)

CommitLog 是“真相”,所有消息最终都在这里。

5.2 ConsumeQueue(逻辑队列索引)

为了让 Consumer 能按 Topic/Queue/Offset 消费,Broker 会维护 ConsumeQueue:

  • ConsumeQueue 以 (Topic, QueueId) 组织
  • 每条记录指向 CommitLog 的 offset/size 等信息
  • Consumer 拉取时,先通过 ConsumeQueue 快速定位消息位置,再读 CommitLog

5.3 IndexFile(按 Key 查消息)

IndexFile 用于“按 key 查消息”(排障很常用):

  • 你给 Message 设置 keys(如 orderId)
  • Broker 构建 key → commitlogOffset 的索引
  • Console/Admin 可以用 key 查询消息

5.4 刷盘与复制

消息写入后,还要考虑两件事:

  • 刷盘(Flush):写到磁盘
  • 复制(Replication):写到从节点/多副本

这两项决定“成功 ACK”到底有多稳。


6. Consumer 消费流程(拉取、处理、提交 Offset)

6.1 Pull 与“看起来像 Push”】【长轮询】

RocketMQ 的 PushConsumer 看起来像“Broker 推”,但本质仍然是:

Consumer 端循环 Pull + Broker 端长轮询(Long Polling)

长轮询的意义:

  • Broker 没新消息时不立刻返回,而是挂起一段时间,有新消息马上返回
  • 减少空轮询,降低延迟

6.2 消费成功:Offset 提交

消费进度 Offset 的概念:

  • 对每个队列都有一个当前 offset:(topic, queueId) -> offset
  • Consumer 拉取一批消息,从 offset 开始
  • 业务处理成功后,提交新的 offset

Offset 存在哪里?

  • 取决于版本与模式,常见是 Broker/本地存储/集中存储的组合(你不用死记,关键是理解:offset 决定“从哪继续”

6.3 消费失败:重试与死信

消费失败的常见流程:

  1. 返回失败/抛异常
  2. RocketMQ 把消息进入重试机制(Retry Topic / 延迟重投)
  3. 超过最大重试次数仍失败 → 进入死信队列(DLQ)

重点:

  • RocketMQ 默认语义偏 至少一次 → 你必须幂等
  • DLQ 不是垃圾桶,必须有人处理(人工后台/自动补偿)

7. Rebalance(队列重新分配)发生了什么

Rebalance 触发条件很常见:

  • Consumer 实例增加/减少
  • Topic 队列数变化
  • 路由变化

Rebalance 结果:

  • 同一消费组内,队列重新分配给不同实例
  • 新接管的实例会从该队列的 offset 继续消费

Rebalance 对你意味着:

  • 会有短暂抖动(尤其是实例频繁伸缩)
  • 顺序消费要更谨慎(队列迁移会影响延迟与稳定性)

8. 三个特殊流程

8.1 顺序消息流程(分区顺序)

核心:同业务键 -> 同队列;同队列 -> 串行消费

流程差异点:

  • Producer:使用 MessageQueueSelector 或 hashKey,把同一个 orderId 的消息路由到固定队列
  • Consumer:使用有序消费(队列级串行),失败会“暂停队列”重试,后续消息会被卡住

8.2 延时消息流程

延时消息的直觉:

  • 先存起来,不立刻可见
  • 到时间后再投递到真实队列供消费

注意:

  • 延时不是精确定时(更像“延后投递”)
  • 延时级别/实现机制不同版本略有差异,但总体流程一致

8.3 事务消息流程(半消息与回查)

事务消息要解决:本地事务与消息发送一致性。

流程(简化):

  1. Producer 发送 半消息(Half Message):Broker 先存,但不让 Consumer 看见
  2. Producer 执行本地事务(DB 更新等)
  3. Producer 发送 commit/rollback 给 Broker
  4. 如果 Broker 长时间没收到结果,会发起 事务回查(询问 Producer:到底成功了吗)
  5. Producer 根据本地事务状态返回 commit/rollback

9. 常见现象的“流程解释”

9.1 为什么会重复消费?

  • Consumer 处理成功但 offset 提交失败/超时
  • Consumer 处理超时被认为失败,触发重试
  • 网络抖动导致 ACK/提交丢失

所以必须幂等。

9.2 为什么会出现堆积(lag)?

  • Producer 写入速度 > Consumer 处理速度
  • Consumer 失败重试导致吞吐下降
  • Rebalance 抖动、消费者实例不足、下游依赖慢

9.3 为什么顺序消息会“卡住”?

  • 顺序消费失败会暂停当前队列重试
  • 一条毒消息会阻塞该队列后续消息

9.4 为什么“发送成功了”还可能丢?

  • ASYNC_FLUSH:成功可能没刷盘
  • ASYNC_MASTER:成功可能没复制到从节点
  • 机器瞬间掉电/磁盘损坏可能导致最后一段丢失

10. 生产建议:把流程跑稳

  1. 至少 2~3 台 NameServer
  2. Broker 选型要明确:吞吐优先还是不丢优先(刷盘/复制策略)
  3. Producer:失败重试 + 失败补偿(落库重发)
  4. Consumer:幂等 + 限制重试 + DLQ 处理闭环
  5. 监控必备:发送失败率、消费失败率、堆积、DLQ 增长、Broker 磁盘、复制滞后
  6. 定期演练:挂 Broker、断网络、磁盘写满、消费者全停

一句话复盘

RocketMQ 的整体工作流程可以记成这条链:

路由发现(NameServer) → 写入存储(Broker CommitLog) → 建索引(ConsumeQueue/Index) → 拉取消费(Consumer Pull/长轮询) → 成功提交 Offset / 失败重试进 DLQ → Rebalance 动态分配队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值