RocketMQ 整体工作流程(端到端)详解:从发消息到消费落库
这篇文档讲清楚 RocketMQ “一条消息从生到死”的全过程:
Producer 怎么找 Broker、Broker 怎么存、Consumer 怎么拉、Offset 怎么提交、失败怎么重试/进 DLQ。
你看完应该能把 RocketMQ 的工作流画出来,并且能解释线上常见现象:堆积、重复消费、顺序、事务、延时。
目录
- 1. 一句话总览:RocketMQ 在干嘛
- 2. 核心角色与它们的职责
- 3. 端到端流程总图
- 4. Producer 发送流程(从路由到 ACK)
- 5. Broker 存储流程(CommitLog → ConsumeQueue → Index)
- 6. Consumer 消费流程(拉取、处理、提交 Offset)
- 7. Rebalance(队列重新分配)发生了什么
- 8. 三个特殊流程
- 9. 常见现象的“流程解释”
- 10. 生产建议:把流程跑稳
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 启动时做几件事:
- 连接/配置多个 NameServer 地址
- 拉取 Topic 路由(包含:Topic 有哪些队列、队列在哪些 Broker 上)
- 缓存路由,并定期更新
注意:Producer 不会每次发消息都问 NameServer,而是用缓存 + 定时刷新,减少中心依赖。
4.2 选择队列(负载均衡)
Topic 一般有多个队列(MessageQueue)。Producer 发送时会:
- 默认轮询/随机选择一个队列做负载均衡
- 也可以按业务键(orderId)自定义选择队列(用于顺序消息)
队列是并行度单位:队列越多,理论并行度越高,但运维成本也越高。
4.3 发送与重试
发送流程(简化):
- Producer 把 Message 发给选中的 Broker
- 若失败/超时:按策略重试(可能换 Broker/换队列)
- 达到重试上限仍失败:返回失败,由业务决定补偿(落库重发等)
生产重点:
- 发送失败不要“吞掉”,必须日志 + 告警 + 补偿方案
- 核心链路建议“落库+异步重试”做最终保障
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 收到消息后:
- 进行校验(Topic、权限、大小等)
- 追加写入 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 消费失败:重试与死信
消费失败的常见流程:
- 返回失败/抛异常
- RocketMQ 把消息进入重试机制(Retry Topic / 延迟重投)
- 超过最大重试次数仍失败 → 进入死信队列(DLQ)
重点:
- RocketMQ 默认语义偏 至少一次 → 你必须幂等
- DLQ 不是垃圾桶,必须有人处理(人工后台/自动补偿)
7. Rebalance(队列重新分配)发生了什么
Rebalance 触发条件很常见:
- Consumer 实例增加/减少
- Topic 队列数变化
- 路由变化
Rebalance 结果:
- 同一消费组内,队列重新分配给不同实例
- 新接管的实例会从该队列的 offset 继续消费
Rebalance 对你意味着:
- 会有短暂抖动(尤其是实例频繁伸缩)
- 顺序消费要更谨慎(队列迁移会影响延迟与稳定性)
8. 三个特殊流程
8.1 顺序消息流程(分区顺序)
核心:同业务键 -> 同队列;同队列 -> 串行消费。
流程差异点:
- Producer:使用 MessageQueueSelector 或 hashKey,把同一个 orderId 的消息路由到固定队列
- Consumer:使用有序消费(队列级串行),失败会“暂停队列”重试,后续消息会被卡住
8.2 延时消息流程
延时消息的直觉:
- 先存起来,不立刻可见
- 到时间后再投递到真实队列供消费
注意:
- 延时不是精确定时(更像“延后投递”)
- 延时级别/实现机制不同版本略有差异,但总体流程一致
8.3 事务消息流程(半消息与回查)
事务消息要解决:本地事务与消息发送一致性。
流程(简化):
- Producer 发送 半消息(Half Message):Broker 先存,但不让 Consumer 看见
- Producer 执行本地事务(DB 更新等)
- Producer 发送 commit/rollback 给 Broker
- 如果 Broker 长时间没收到结果,会发起 事务回查(询问 Producer:到底成功了吗)
- 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. 生产建议:把流程跑稳
- 至少 2~3 台 NameServer
- Broker 选型要明确:吞吐优先还是不丢优先(刷盘/复制策略)
- Producer:失败重试 + 失败补偿(落库重发)
- Consumer:幂等 + 限制重试 + DLQ 处理闭环
- 监控必备:发送失败率、消费失败率、堆积、DLQ 增长、Broker 磁盘、复制滞后
- 定期演练:挂 Broker、断网络、磁盘写满、消费者全停
一句话复盘
RocketMQ 的整体工作流程可以记成这条链:
路由发现(NameServer) → 写入存储(Broker CommitLog) → 建索引(ConsumeQueue/Index) → 拉取消费(Consumer Pull/长轮询) → 成功提交 Offset / 失败重试进 DLQ → Rebalance 动态分配队列
893

被折叠的 条评论
为什么被折叠?



