四个角色先认脸
RocketMQ 的世界里有四个角色:NameServer(注册中心,管路由)、Broker(存储与转发主力)、Producer 与 Consumer(收发两端)。打地基的一篇已经见过后两位,这里重点拆前两位,再讲 Broker 的高可用演进。
NameServer:故意的「无状态」
NameServer 做两件事:Broker 注册(每 30 秒一次心跳),客户端路由发现(生产者/消费者来问「哪个 Broker 管 Topic X」)。它最特别的设计是节点之间互不通信:每台 NameServer 独立维护自己的路由表,Broker 的心跳同时发给所有节点,谁的数据对齐了没有没人管——纯最终一致。
为什么不学 Kafka 用 ZooKeeper 做强一致注册中心?RocketMQ 的作者算过账:路由数据是「软状态」,短暂不一致的代价(某台客户端晚几秒发现 Broker 变化)远小于维护强一致集群的复杂度。NameServer 挂一台,剩下的照常服务,部署两台起步、三台稳妥。用一致性换简单,是架构题的常见正确答案。
CommitLog:所有 Topic 挤一条高速路
Kafka 的存储是「一个 partition 一个日志文件」,而 RocketMQ 是所有 Topic 的消息混写进同一个 CommitLog(默认 1GB 一个文件段),再由 ConsumeQueue 为每个队列维护定长索引(指向 CommitLog 里的物理位置)。
这个设计针对的是 Kafka 的一个隐患:partition 数量暴涨后,写入分散在几百个文件里,顺序写退化成「跨文件的近似随机写」,性能塌方。RocketMQ 把写入收拢到一条文件流,不管多少 Topic 多少队列,磁盘看到的永远是一条顺序写——几千个 Topic 也不怕。代价是读消息要先查 ConsumeQueue 再去 CommitLog 定位,多一次寻址,用读的间接性换写的纯粹性。这就是第 3 篇选型表里「RocketMQ 业务系统首选」的底层注脚:业务系统的 Topic 数往往比日志管道多得多。
高可用演进:从手工挡把到自动挡
| 模式 | 机制 | 主挂了怎么办 |
|---|---|---|
| 传统主从(4.x 早期) | 一主多从,同步/异步复制 | 人工改配置切换,客户端感知延迟 |
| Controller 模式(4.9+) | 独立控制器管理主备切换 | 自动切换,秒级恢复 |
| Dledger 集群(4.5+) | 基于 Raft,多数派写入自动选主 | 自动选主,无需人工介入 |
Dledger 的思路和 MySQL 组复制、etcd 是同门:三台以上节点组成 Raft 组,写请求必须拿到多数派确认才返回成功,Leader 挂了活着的节点自动投票选出新 Leader。配合多数派写入,「不丢」的保证从配置纪律升级成了协议保证。代价是多数派必须在线:三节点坏一台没事,坏两台整个组只读不可写。
生产部署的参考答案
- NameServer:3 台,与应用同机部署也行(够轻量),独立部署更稳;
- Broker:核心业务用 Dledger 三副本起步,或 2 主 2 从同步复制;磁盘 SSD,CommitLog 与 ConsumeQueue 可以分盘,消息留存期按流量算好容量;
- 刷盘复制组合:交易链路同步刷盘+同步复制(或 Dledger 多数派),埋点日志异步刷盘+异步复制;
- 参数红线:消息体压在 128KB 内(默认单条上限 4MB,大消息走文件引用),别让大消息把 CommitLog 搅成泥石流。
小结
RocketMQ 的骨架三句话:NameServer 无状态换来极简运维,CommitLog 混写守住顺序写红利,Dledger 用 Raft 把高可用从人肉升级为协议。看懂这三点,控制台上那些配置项就都有了出处。
单系统的架构讲完了,下一站把镜头拉远:跨机房容灾、双活部署与脑裂防范——当机房整个没了,消息系统怎么活下来。
评论 (0)