TL;DR
场景: 电商/金融/日志分发需要解耦、削峰、可靠投递与可观测消费。
结论: RocketMQ 用”路由中心(NameServer)+ 存储转发(Broker)+ 客户端缓存路由”完成高吞吐与可用性权衡,关键在路由、刷盘/复制、消费位点与重试语义。
产出: 一篇覆盖发展脉络、角色职责、部署拓扑与发送/消费全链路流程的工程化说明稿。
RocketMQ
基本介绍
RocketMQ 的发展历程与阿里技术演进密不可分。其前身 MetaQ 最早名为 Metamorphosis(变形记),这个名字不仅是对作家卡夫卡中篇小说代表作的致敬,更暗示了这款消息中间件将经历从 Kafka 衍生到独立发展的蜕变过程。
在阿里技术体系内,MetaQ 经历了三个重要发展阶段:
- 初始阶段(MetaQ 1.x): 基于 Kafka 核心思想,采用 Java 重写实现
- 成熟阶段(MetaQ 2.x): 针对电商场景进行深度优化
- 开源阶段(MetaQ 3.x/RocketMQ): 正式开源并成为 Apache 顶级项目
技术选型考量:
- 技术栈统一:当时阿里技术体系以 Java 为主(占比超过80%)
- 性能需求:电商场景需要更高的吞吐量(峰值超过百万级TPS)
- 功能扩展:需要支持事务消息、顺序消息等金融级特性
使用场景
应用解耦
系统的耦合性越高,容错性就越低。以电商应用为例,用户创建订单是一个复杂的业务流程,涉及多个子系统的协同工作:
- 订单系统:记录订单基本信息
- 库存系统:扣减商品库存
- 物流系统:生成配送单
- 支付系统:处理支付流程
- 营销系统:计算优惠和积分
通过引入消息队列,可以将这些系统解耦,实现最终一致性,保证核心业务流程不中断。
流量削峰
应用系统经常面临突发流量冲击的挑战。消息队列的削峰能力体现在:
- 所有请求先进入消息队列缓冲
- 后端系统按照自身处理能力匀速消费消息
- 超量请求在队列中排队等待,不会直接冲击后端
数据分发
现代系统架构中,数据往往需要在多个系统间流转。消息队列提供发布/订阅模式,让各系统按需订阅感兴趣的数据。
部署架构
角色介绍
Producer(生产者)
Producer 是消息队列系统中负责创建和发送消息的客户端角色。它负责将业务系统产生的消息按照指定格式封装后发送到消息队列中。
Consumer(消费者)
Consumer 是消息队列系统中负责接收和处理消息的客户端角色。它从消息队列中获取消息并进行业务处理。Consumer 通常以消费者组的形式工作。
Broker(代理服务器)
Broker 是消息队列系统的核心组件,负责消息的存储和转发。其主要功能包括:
- 消息接收:接收 Producer 发送的消息
- 消息存储:将消息持久化到磁盘
- 消息投递:将消息推送给 Consumer 或等待 Consumer 拉取
NameServer(命名服务)
NameServer 是轻量级的服务发现组件,主要功能包括:
- Broker管理:维护所有 Broker 的注册信息和健康状态
- 路由管理:为 Producer 和 Consumer 提供 Topic-Broker 的路由信息
- 无状态设计:多个 NameServer 实例之间互不通信
Topic(主题)
Topic 是消息的逻辑分类,具有以下特性:
- 一个 Topic 包含多个 Message Queue(分区)
- Producer 发送消息时需要指定 Topic
- Consumer 订阅消息时需要指定 Topic
Message Queue(消息队列)
Message Queue 是 Topic 的分区实现,具有以下特点:
- 一个 Topic 可以分为多个 Message Queue,实现并行处理
- 每个 Message Queue 保证 FIFO(先进先出)顺序
各角色连接机制
NameServer:
- RocketMQ 的核心组件之一,作为轻量级的注册中心
- 主要负责管理 Broker 的路由信息
- 采用无状态设计,各节点之间相互独立,不进行数据同步
- 建议部署 3-5 个 NameServer 节点以保证高可用性
Broker:
- 作为消息存储和转发的核心节点
- 部署架构采用主从模式
- Master 节点负责处理所有的读写请求
- Slave 节点主要用于数据备份和灾备恢复
- Broker 启动后会立即与 NameServer 集群中的所有节点建立长连接
Producer:
- 首先会随机选择 NameServer 集群中的一个节点建立长连接
- 定时(默认30秒)从 NameServer 获取 Topic 的路由信息
- Producer 的设计是完全无状态的,可以轻松实现横向扩展
Consumer:
- 连接机制与 Producer 类似,首先随机连接 NameServer 集群中的一个节点获取路由信息
- 与 Producer 不同的是,Consumer 会同时与 Master 和 Slave Broker 建立连接
- 采用拉模式获取消息
Producer 消息发送流程
-
详细工作流程:
- 初始化时从 NameServer 获取 Topic 路由信息
- 维护两个本地缓存:
topicPublishInfoTable: Topic 发布信息brokerAddrTable: Broker 地址表
- 消息发送时:
- 选择 MessageQueue(轮询/哈希等策略)
- 根据 Broker 名称获取 Master 地址
- 建立网络连接发送消息
-
容错机制:
- 默认重试 2 次(可配置)
- 故障转移策略:优先选择其他 Broker,次选同 Broker 的 Slave
Consumer 消息消费流程
-
详细工作流程:
- 启动时从 NameServer 获取 Topic 路由信息
- 采用长轮询机制(Pull 模式)
- 消费进度管理:本地维护 offset,定时持久化到 Broker
-
负载均衡:
- 每 20 秒重新分配队列(可配置)
- 支持多种分配策略
-
消费模式:
- 集群模式(CLUSTERING):每条消息只被一个消费者消费
- 广播模式(BROADCASTING):每条消息被所有消费者消费
错误速查
| 症状 | 根因 | 定位 | 修复 |
|---|---|---|---|
| 发送报错 NO_ROUTE_INFO_OF_THIS_TOPIC | Topic 未创建/未注册到 NameServer | mqadmin 查询 Topic 路由 | 生产环境显式创建 Topic |
| Producer send timeout / RT 飙升 | Broker 负载高、磁盘刷盘慢、网络抖动 | Broker 磁盘/IO、线程池堆积 | 优化刷盘/复制策略与磁盘 |
| 消费积压持续增长 | 消费能力不足、消费线程阻塞 | 消费 TPS、堆积量、消费耗时 | 提升并发/批量消费 |
| 重复消费/幂等问题 | 至少一次投递语义 + 重试 | 消费日志:同 key 多次 | 业务侧幂等 |
| Broker 启动后 NameServer 无路由 | Broker 未能连上所有 NameServer | Broker 注册日志 | 校验 NameServer 地址列表 |