RocketMQ 集群介绍
九、RocketMQ 集群部署与高可用机制
RocketMQ 集群的核心价值在于通过多节点部署实现高可用、高吞吐和数据一致性,其集群设计围绕「Broker 主从」和「NameServer 无状态集群」展开,核心分为传统主从模式和基于 Raft 协议的 Dledger 自动容灾模式。本文详细讲解集群部署方式、选主机制、核心配置、优缺点及脑裂防护方案。
一、集群部署模式(增强版)
1. 基础部署模式对比
| 部署模式 | 架构组成 | 核心特点 | 可用性 | 数据一致性 | 适用场景 |
|---|---|---|---|---|---|
| 单 Master | 1 个 Broker(Master)+ 1+ NameServer | 部署最简,无冗余 | 0(宕机即不可用) | - | 本地测试、功能验证 |
| 多 Master | N 个 Broker(均为 Master)+ 1+ NameServer | 写性能最高,无同步开销 | 部分可用(单节点宕机则对应队列不可用) | 弱(节点宕机丢失未持久化数据) | 非核心业务、临时测试 |
| 多 Master + 多 Slave(传统主从) | 每个 Master 对应 1+ Slave + 1+ NameServer | 主写从读,需手动切换 | 高(需人工介入恢复) | 异步复制:弱 同步双写:强 | 中小生产环境、可接受手动运维 |
| Dledger 集群(Raft 模式) | 3/5 个 Broker 组成 Raft Group + 1+ NameServer | 自动选主、自动故障转移 | 极高(秒级自动恢复) | 强(Quorum 写入确认) | 核心生产环境、金融级场景 |
2. 传统主从模式(Master-Slave)详细配置
2.1 核心配置说明(broker.conf)
传统主从模式需为每个 Master/Slave 配置独立文件,核心配置项如下:
# ===================== 公共配置(所有节点)=====================
brokerClusterName=MyRocketMQCluster # 集群名称(所有节点必须一致)
brokerId=0 # Master 为 0,Slave 为 1/2/3...(数字越大优先级越低)
listenPort=10911 # Broker 服务端口(Slave 可与 Master 不同)
namesrvAddr=192.168.1.10:9876;192.168.1.11:9876 # NameServer 集群地址
storePathRootDir=/data/rocketmq/store # 消息存储根目录
storePathCommitLog=/data/rocketmq/store/commitlog # 提交日志存储路径
autoCreateTopicEnable=true # 自动创建 Topic(生产建议关闭)
deleteWhen=04 # 凌晨 4 点清理过期消息
fileReservedTime=72 # 消息保留时长(小时)
mapedFileSizeCommitLog=1073741824 # CommitLog 文件大小(默认 1GB)
# ===================== Master 节点专属配置 =====================
brokerName=broker-a # 主从节点需同名(标识同一组)
brokerRole=SYNC_MASTER # 主节点角色:SYNC_MASTER(同步双写)/ASYNC_MASTER(异步复制)
flushDiskType=SYNC_FLUSH # 刷盘策略:SYNC_FLUSH(同步刷盘)/ASYNC_FLUSH(异步刷盘)
# ===================== Slave 节点专属配置 =====================
brokerName=broker-a # 必须与对应 Master 一致
brokerId=1 # Slave 标识(非 0 即可)
brokerRole=SLAVE # 从节点角色
flushDiskType=ASYNC_FLUSH # Slave 建议异步刷盘
pullMessageThreadPoolNums=32 # 从节点拉取线程数(优化读性能)
2.2 传统主从部署步骤(以 1 Master + 1 Slave 为例)
-
环境准备
- 两台服务器(如 192.168.1.10、192.168.1.11),均安装 RocketMQ
- 配置
JAVA_HOME,关闭防火墙/SELINUX - 提前启动 NameServer 集群(至少 2 节点):
# 启动 NameServer(所有节点执行) nohup sh bin/mqnamesrv & # 验证 NameServer 启动 jps | grep NamesrvStartup
-
Master 节点配置与启动
# 1. 编辑 Master 配置文件 vi conf/broker-a-master.conf # 内容如上 Master 配置 # 2. 启动 Master nohup sh bin/mqbroker -c conf/broker-a-master.conf & # 3. 验证 Master 注册(NameServer 节点执行) sh bin/mqadmin clusterList -n 192.168.1.10:9876 -
Slave 节点配置与启动
# 1. 编辑 Slave 配置文件 vi conf/broker-a-slave.conf # 内容如上 Slave 配置 # 2. 启动 Slave nohup sh bin/mqbroker -c conf/broker-a-slave.conf & # 3. 验证主从关系 sh bin/mqadmin clusterList -n 192.168.1.10:9876 # 可看到 broker-a 包含 Master/Slave
2.3 传统主从故障恢复(手动切换)
当 Master 宕机时,需手动将 Slave 提升为 Master:
# 1. 停止故障 Master 节点(若未宕机)
sh bin/mqshutdown broker
# 2. 修改 Slave 配置文件
vi conf/broker-a-slave.conf
brokerId=0 # 改为 0(Master 标识)
brokerRole=SYNC_MASTER # 改为主节点角色
# 3. 重启 Slave 节点
sh bin/mqshutdown broker
nohup sh bin/mqbroker -c conf/broker-a-slave.conf &
# 4. 通知客户端更新路由(可选,客户端会自动从 NameServer 拉取新路由)
3. Dledger 集群模式(推荐生产)
3.1 Dledger 核心原理
Dledger 是 RocketMQ 基于 Raft 协议实现的分布式日志复制框架,核心解决传统主从「手动切换」和「数据不一致」问题,其核心特性:
- 节点角色:Leader(主)、Follower(从)、Candidate(候选者)
- 选主规则:需获得超过半数节点投票(N/2 + 1)
- 数据复制:Leader 接收写请求后,同步日志到 Follower,需多数节点确认后才返回成功
- 故障转移:Leader 宕机后,Follower 自动触发选举,秒级选出新 Leader
3.2 Dledger 集群配置(3 节点示例)
核心配置文件(dledger-broker-n0.conf,节点 1)
# ===================== 基础配置 =====================
brokerClusterName=DledgerCluster
brokerName=broker-dledger # 所有节点必须同名
brokerId=0 # Dledger 模式下 brokerId 无意义,仅需唯一
listenPort=10911
namesrvAddr=192.168.1.10:9876;192.168.1.11:9876
storePathRootDir=/data/rocketmq/dledger/store
storePathCommitLog=/data/rocketmq/dledger/store/commitlog
# ===================== Dledger 核心配置 =====================
enableDLegerCommitLog=true # 开启 Dledger 模式(核心开关)
dLegerGroup=broker-dledger-group # Raft Group 名称(所有节点一致)
# 集群节点列表:格式 节点ID-IP:端口(端口为 Dledger 通信端口,非 Broker 端口)
dLegerPeers=n0-192.168.1.12:40911;n1-192.168.1.13:40911;n2-192.168.1.14:40911
dLegerSelfId=n0 # 当前节点 ID(每个节点不同:n0/n1/n2)
dLegerElectorType=RAFT # 选举类型(固定为 RAFT)
# ===================== 性能配置 =====================
sendMessageThreadPoolNums=16 # 发送线程数
pullMessageThreadPoolNums=32 # 拉取线程数
flushDiskType=ASYNC_FLUSH # Dledger 模式下建议异步刷盘(由 Raft 保证一致性)
节点 2(dledger-broker-n1.conf)关键差异
dLegerSelfId=n1 # 节点 ID 改为 n1
listenPort=10921 # Broker 端口可不同(避免冲突)
节点 3(dledger-broker-n2.conf)关键差异
dLegerSelfId=n2 # 节点 ID 改为 n2
listenPort=10931 # Broker 端口可不同
3.3 Dledger 集群部署步骤
- 环境准备:3 台服务器(192.168.1.12/13/14),已安装 RocketMQ,启动 NameServer 集群。
- 配置文件分发:将上述 3 个配置文件分别放到对应节点的
conf/目录。 - 启动集群(所有节点依次执行):
# 节点 1 nohup sh bin/mqbroker -c conf/dledger-broker-n0.conf & # 节点 2 nohup sh bin/mqbroker -c conf/dledger-broker-n1.conf & # 节点 3 nohup sh bin/mqbroker -c conf/dledger-broker-n2.conf & - 验证集群状态:
# 查看 Dledger 节点角色 sh bin/mqadmin getBrokerStatus -n 192.168.1.10:9876 -b 192.168.1.12:10911 # 输出示例:role=LEADER 或 FOLLOWER # 查看集群整体状态 sh bin/mqadmin clusterList -n 192.168.1.10:9876
二、集群选主机制(深度解析)
1. 传统主从模式:无自动选主
传统主从模式无内置选主逻辑,Master 身份由配置文件 brokerId=0 和 brokerRole=SYNC_MASTER/ASYNC_MASTER 固定:
- 启动时,Slave 会主动连接 Master 同步数据,Master 无需「选举」;
- Master 宕机后,Slave 仍为 Slave 角色,需人工修改配置将 Slave 改为 Master;
- 客户端仅向 Master 写消息,Slave 仅提供读能力,无自动切换逻辑。
2. Dledger 集群:Raft 选主流程(完整步骤)
Dledger 选主基于 Raft 协议,核心分为「初始选举」和「故障重选」两个阶段,全程自动执行:
2.1 初始选举流程
graph TD
A[所有节点启动] --> B["初始状态为 Follower,启动选举超时器(默认 1000ms)"]
B --> C{"是否收到 Leader 心跳?"}
C -- 是 --> B["重置超时器,保持 Follower"]
C -- 否 --> D["转为 Candidate,发起投票请求"]
D --> E["向所有节点发送 VoteRequest(包含自身任期、日志索引)"]
E --> F{"是否获得半数以上投票?"}
F -- 是 --> G["转为 Leader,定期发送心跳(默认 200ms)"]
F -- 否 --> H["等待超时,重新发起投票"]
G --> I["接收写请求,同步日志到 Follower"]
2.2 故障重选流程(Leader 宕机)
graph TD
A["Leader 宕机,停止发送心跳"] --> B["Follower 选举超时器触发"]
B --> C["Follower 转为 Candidate,自增任期,发起投票"]
C --> D["节点间投票,遵循 Raft 投票规则"]
D --> E{"是否有节点获得半数以上投票?"}
E -- 是 --> F["新 Leader 产生,接管写服务"]
E -- 否 --> G["重新投票(任期自增)"]
F --> H["新 Leader 同步日志到剩余 Follower"]
H --> I["客户端从 NameServer 获取新 Leader 地址,恢复写服务"]
2.3 Raft 投票核心规则(防脑裂关键)
- 任期优先:高任期节点拒绝低任期节点的投票请求;
- 日志完整性:仅投票给日志比自己新的 Candidate(保证数据一致性);
- 多数票规则:必须获得 > N/2 节点投票才能成为 Leader(3 节点需 2 票,5 节点需 3 票);
- 单任期单 Leader:同一任期内仅能有一个 Leader。
3. 选主关键配置项
| 配置项 | 默认值 | 说明 | 调优建议 |
|---|---|---|---|
dLegerElectorType | RAFT | 选举类型(固定为 RAFT) | 不可修改 |
dledger.election.timeout.ms | 1000 | 选举超时时间(Follower 未收到心跳触发选举) | 生产建议 1000-3000ms |
dledger.heartbeat.interval.ms | 200 | Leader 心跳发送间隔 | 建议 200-500ms(过短增加网络开销) |
dledger.commit.timeout.ms | 2000 | 日志提交超时时间 | 建议 1000-3000ms |
dledger.max.wait.leader.ms | 60000 | 最大等待 Leader 时间 | 保持默认即可 |
三、核心配置项详解(按模块分类)
1. 集群基础配置
| 配置项 | 作用 | 取值示例 | 生产建议 |
|---|---|---|---|
brokerClusterName | 集群名称(标识同一集群) | MyRocketMQCluster | 所有节点保持一致 |
brokerName | 主从组/DLedger 组名称 | broker-a | 同一组节点必须一致 |
brokerId | Master/Slave 标识 | Master=0,Slave=1+ | Dledger 模式下无意义 |
namesrvAddr | NameServer 集群地址 | 192.168.1.10:9876;192.168.1.11:9876 | 至少配置 2 个,用分号分隔 |
listenPort | Broker 服务端口 | 10911 | 不同节点可不同,避免端口冲突 |
2. Dledger 专属配置
| 配置项 | 作用 | 取值示例 | 生产建议 |
|---|---|---|---|
enableDLegerCommitLog | 开启 Dledger 模式 | true/false | 生产必须设为 true |
dLegerGroup | Raft Group 名称 | broker-dledger-group | 同一 DLedger 集群必须一致 |
dLegerPeers | 集群节点列表 | n0-192.168.1.12:40911;n1-192.168.1.13:40911 | 端口建议 40911/40912 等,避免冲突 |
dLegerSelfId | 当前节点 ID | n0/n1/n2 | 每个节点唯一,与 peers 中的 ID 对应 |
3. 性能与一致性配置
| 配置项 | 作用 | 取值 | 生产建议 |
|---|---|---|---|
brokerRole | 节点角色 | SYNC_MASTER/ASYNC_MASTER/SLAVE | 传统主从:Master 用 SYNC_MASTER;Dledger 模式无需配置 |
flushDiskType | 刷盘策略 | SYNC_FLUSH/ASYNC_FLUSH | 传统主从 Master:SYNC_FLUSH;Dledger 模式:ASYNC_FLUSH |
fileReservedTime | 消息保留时长 | 72(小时) | 核心业务可设为 168(7 天),非核心设为 24 |
mapedFileSizeCommitLog | CommitLog 文件大小 | 1073741824(1GB) | 保持默认,过大易导致磁盘 IO 卡顿 |
四、集群优缺点(增强版)
1. 传统主从集群(多 Master + 多 Slave)
优点
- 部署简单:配置少,运维门槛低;
- 性能可控:主写从读,可灵活调整 Slave 数量提升读性能;
- 资源开销低:无 Raft 协议的日志复制和投票开销;
- 兼容性好:支持所有 RocketMQ 版本,无版本限制。
缺点
- 无自动选主:Master 宕机需人工切换,恢复时间长(分钟级);
- 脑裂风险:网络分区时,Slave 被手动提升为 Master,原 Master 恢复后出现双 Master;
- 数据一致性弱:异步复制模式下,Master 宕机可能丢失未同步数据;
- 运维成本高:需人工监控节点状态,故障时需及时介入。
2. Dledger 集群(Raft 模式)
优点
- 自动选主/故障转移:Leader 宕机后秒级选出新 Leader,无需人工干预;
- 强数据一致性:基于 Quorum 写入规则,仅当多数节点确认日志后才返回成功;
- 防脑裂:Raft 协议的「多数票规则」从根本上避免脑裂;
- 高可用:3 节点集群可容忍 1 节点故障,5 节点可容忍 2 节点故障;
- 运维简化:无需手动切换主从,降低人工操作风险。
缺点
- 资源开销高:
- 存储开销:每份数据需存储 3/5 副本(传统主从仅 2 副本);
- 网络开销:Leader 需同步日志到 Follower,投票和心跳增加网络流量;
- 部署复杂度高:需配置 Raft 节点列表、端口等,配置错误易导致集群不可用;
- 最小节点要求:至少 3 节点(2 节点无法满足多数票规则),小型业务成本高;
- 网络敏感:Raft 协议对网络延迟敏感(>10ms 可能导致选举不稳定),不适合跨地域部署;
- 版本限制:仅支持 RocketMQ 4.5+ 版本。
五、脑裂问题分析与防护
1. 脑裂定义
脑裂是指集群因网络分区导致「一个集群被拆分为多个独立子集群」,每个子集群各自选出 Leader,导致数据不一致、重复写入等问题。
2. 不同模式下的脑裂风险
| 集群模式 | 是否存在脑裂 | 风险原因 | 防护方案 |
|---|---|---|---|
| 传统主从 | 高风险 | 网络分区后,人工误操作将 Slave 提升为 Master,原 Master 恢复后形成双 Master | 1. 提升 Slave 前先确认原 Master 彻底宕机; 2. 采用 VIP 漂移+仲裁机制(如 ZooKeeper 确认); 3. 禁止跨机房部署传统主从 |
| Dledger 集群 | 无风险 | Raft 协议的「多数票规则」: 1. 网络分区后,仅能有一个子集群满足「多数节点」条件,才能选出 Leader; 2. 分区恢复后,旧 Leader 发现任期更低,自动转为 Follower | 1. 配置奇数节点(3/5); 2. 合理设置选举超时时间(1000-3000ms); 3. 避免跨高延迟网络部署 |
3. Dledger 防脑裂核心机制
- 任期机制:每个节点维护「任期号」,高任期节点拒绝低任期节点的请求,分区恢复后旧 Leader 自动降级;
- 多数票规则:网络分区后,只有包含多数节点的子集群能选出 Leader,其他子集群无法选举;
- 日志校验:Candidate 需日志足够新才能获得投票,避免数据不一致的节点成为 Leader;
- 心跳检测:Leader 定期发送心跳,Follower 超时未收到则触发选举,保证 Leader 唯一性。
六、生产环境最佳实践
1. 集群规划建议
| 业务规模 | 集群模式 | 节点配置 | 核心配置 |
|---|---|---|---|
| 小型业务(QPS < 1w) | Dledger 3 节点 | 3 台 8C16G 服务器,单盘 > 200GB | 异步刷盘,消息保留 24 小时 |
| 中型业务(1w < QPS < 10w) | Dledger 3 节点 + 多组 Broker | 3 节点 DLedger 为一组,部署 2-3 组 | 每组独立 Raft Group,NameServer 2 节点 |
| 大型业务(QPS > 10w) | Dledger 5 节点 + 多组 Broker | 5 节点 DLedger 为一组,部署 3+ 组 | 跨可用区部署(同地域),开启消息轨迹 |
2. 关键运维建议
- NameServer 集群:至少 2 节点,无状态部署,无需主从;
- Dledger 节点:
- 优先选择奇数节点(3/5),避免偶数节点导致投票平局;
- 同地域部署(跨可用区),避免跨地域网络延迟;
- 存储目录使用独立磁盘(SSD 最佳),避免 IO 竞争;
- 监控核心指标:
- DLedger 节点角色(Leader/Follower);
- 选举次数(频繁选举说明网络不稳定);
- 日志复制延迟(Leader 与 Follower 日志索引差);
- 消息堆积量(Leader 宕机后可能短暂堆积);
- 灾备演练:定期手动关闭 Leader 节点,验证自动选主和业务恢复能力。
七、总结
核心关键点
- 集群选型:核心业务优先选择 Dledger 3/5 节点集群(自动高可用、防脑裂),中小业务可先用传统主从(降低成本);
- 选主机制:传统主从无自动选主,Dledger 基于 Raft 协议实现「多数票选举 + 任期机制」,保证 Leader 唯一性;
- 脑裂防护:Dledger 依靠 Raft 协议从底层避免脑裂,传统主从需人工规范操作+VIP 仲裁;
- 配置核心:Dledger 集群需重点配置
dLegerPeers和dLegerSelfId,保证节点列表与实际部署一致; - 运维重点:监控 DLedger 选举次数和日志复制延迟,定期演练故障恢复。
最终建议
- 测试环境:单 Master 或多 Master;
- 中小生产:传统主从(SYNC_MASTER + Slave)+ VIP 漂移;
- 核心生产:Dledger 3 节点集群(强烈推荐);
- 超大规模生产:Dledger 5 节点集群 + 多组 Broker 水平扩展。