集群部署
生产环境中,为了保证消息系统的高可用和高性能,需要部署 RocketMQ 集群。本章将详细介绍各种集群部署方案。
部署架构概述
RocketMQ 支持多种部署架构,根据业务需求选择合适的方案:
| 架构模式 | 说明 | 适用场景 |
|---|---|---|
| 单 Master | 只有一个 Broker 节点 | 开发测试环境 |
| 多 Master | 多个 Master Broker,无 Slave | 允许少量消息丢失的场景 |
| 多 Master 多 Slave(异步复制) | Master 异步复制到 Slave | 高可用,允许少量丢失 |
| 多 Master 多 Slave(同步双写) | Master 同步写入 Slave | 高可用,不丢失消息 |
| Controller 模式 | 支持自动主从切换 | 生产环境,需要自动故障转移 |
单 Master 部署
单 Master 部署最简单,但存在单点故障风险,仅适用于开发测试环境。
启动命令:
# 启动 NameServer
nohup sh bin/mqnamesrv &
# 启动 Broker
nohup sh bin/mqbroker -n localhost:9876 &
注意事项:
- Broker 宕机会导致服务不可用
- 机器故障可能导致消息丢失
- 仅用于开发测试,不推荐生产使用
多 Master 部署
多 Master 部署没有 Slave 节点,所有 Broker 都是 Master,提供较高的吞吐量。
配置示例
Broker-A 配置(broker-a.properties):
# 基础配置
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 存储配置
storePathRootDir = /data/rocketmq/store
storePathCommitLog = /data/rocketmq/store/commitlog
# 刷盘配置
flushDiskType = ASYNC_FLUSH
Broker-B 配置(broker-b.properties):
# 基础配置
brokerClusterName = DefaultCluster
brokerName = broker-b
brokerId = 0
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 存储配置
storePathRootDir = /data/rocketmq/store
storePathCommitLog = /data/rocketmq/store/commitlog
# 刷盘配置
flushDiskType = ASYNC_FLUSH
启动命令
# 在机器 A 上启动
nohup sh bin/mqbroker -c conf/broker-a.properties &
# 在机器 B 上启动
nohup sh bin/mqbroker -c conf/broker-b.properties &
优缺点
优点:
- 配置简单,易于维护
- 所有节点均可写入,吞吐量高
- 单节点故障不影响其他节点
缺点:
- 节点宕机期间消息不可用
- 机器故障可能导致消息丢失
- 不适合对可靠性要求高的场景
多 Master 多 Slave 部署
多 Master 多 Slave 架构是生产环境常用的部署方式,每个 Master 配备一个或多个 Slave 节点。
异步复制模式
Master 收到消息后立即返回,异步复制到 Slave。
Master 配置:
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
brokerRole = ASYNC_MASTER
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 刷盘配置
flushDiskType = ASYNC_FLUSH
# 主从同步配置
haListenPort = 10912
haMasterAddress = 192.168.1.10:10912
Slave 配置:
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 1
brokerRole = SLAVE
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 主从同步配置
haListenPort = 10912
haMasterAddress = 192.168.1.10:10912
特点:
- Master 写入成功即返回,性能高
- Slave 异步复制,有短暂延迟
- Master 故障可能丢失少量未同步的消息
同步双写模式
Master 收到消息后同步写入 Slave,两者都成功才返回。
Master 配置:
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
brokerRole = SYNC_MASTER
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 刷盘配置
flushDiskType = SYNC_FLUSH
# 主从同步配置
haListenPort = 10912
Slave 配置:
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 1
brokerRole = SLAVE
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
listenPort = 10911
# 主从同步配置
haListenPort = 10912
haMasterAddress = 192.168.1.10:10912
特点:
- Master 和 Slave 同时写入成功才返回
- 数据不丢失,可靠性高
- 性能相对较低,延迟增加
两种模式对比
| 特性 | 异步复制 | 同步双写 |
|---|---|---|
| 性能 | 高 | 中 |
| 可靠性 | 中(可能丢失少量消息) | 高(不丢消息) |
| 延迟 | 低 | 高 |
| 适用场景 | 允许少量丢失 | 不允许丢失 |
Controller 模式(自动主从切换)
RocketMQ 5.x 引入了 Controller 模式,支持 Broker 主从自动切换,实现故障自动转移。
架构图
Controller 部署
Controller 提供选主能力,需要部署 3 个及以上节点(遵循 Raft 多数派协议)。
方式一:嵌入 NameServer 部署
在 NameServer 配置文件中添加 Controller 配置:
# namesrv.conf
# 开启 Controller 功能
enableControllerInNamesrv = true
# DLedger Raft Group 配置
controllerDLegerGroup = controller-group
controllerDLegerPeers = n0-192.168.1.1:9877;n1-192.168.1.2:9877;n2-192.168.1.3:9877
controllerDLegerSelfId = n0
# Controller 存储路径(重要,不可删除)
controllerStorePath = /data/rocketmq/controller
# 是否可以从 SyncStateSet 以外选举 Master
enableElectUncleanMaster = false
# Broker 角色变更时是否通知
notifyBrokerRoleChanged = true
启动 NameServer:
nohup sh bin/mqnamesrv -c conf/namesrv.conf &
方式二:独立部署 Controller
# controller.conf
controllerDLegerGroup = controller-group
controllerDLegerPeers = n0-192.168.1.1:9877;n1-192.168.1.2:9877;n2-192.168.1.3:9877
controllerDLegerSelfId = n0
controllerStorePath = /data/rocketmq/controller
启动 Controller:
nohup sh bin/mqcontroller -c conf/controller.conf &
重要参数说明:
| 参数 | 说明 |
|---|---|
enableControllerInNamesrv | NameServer 是否开启 Controller 功能 |
controllerDLegerGroup | DLedger Raft Group 名称 |
controllerDLegerPeers | Controller 集群节点信息 |
controllerDLegerSelfId | 当前节点 ID |
controllerStorePath | Controller 日志存储路径 |
enableElectUncleanMaster | 是否允许从同步集合外选举 Master |
Broker 配置
在 Controller 模式下,Broker 需要配置以下参数:
# broker.conf
# 开启 Controller 模式
enableControllerMode = true
# Controller 地址
controllerAddr = 192.168.1.1:9877;192.168.1.2:9877;192.168.1.3:9877
# NameServer 地址
namesrvAddr = 192.168.1.1:9876;192.168.1.2:9876
# 同步副本数
inSyncReplicas = 2
minInSyncReplicas = 1
# 消息需要复制到所有同步副本才返回成功
allAckInSyncStateSet = true
# Slave 跟不上 Master 的最大时间间隔
haMaxTimeSlaveNotCatchup = 15000
关键配置参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
enableControllerMode | false | Controller 模式总开关 |
controllerAddr | - | Controller 地址,分号分隔 |
syncBrokerMetadataPeriod | 5000 | 向 Controller 同步信息的间隔 |
checkSyncStateSetPeriod | 5000 | 检查同步状态集合的间隔 |
haMaxTimeSlaveNotCatchup | 15000 | Slave 最大落后时间(ms) |
allAckInSyncStateSet | false | 消息是否需要复制到所有同步副本 |
inSyncReplicas | 1 | 需保持同步的副本数 |
minInSyncReplicas | 1 | 最小同步副本数 |
启动 Broker
Controller 模式下,Broker 无需指定 brokerId 和 brokerRole,由 Controller 自动分配:
nohup sh bin/mqbroker -c conf/broker.conf &
故障切换流程
升级注意事项
从传统 Master-Slave 架构升级到 Controller 模式:
- 升级 NameServer:直接升级,无兼容性问题
- 升级 Broker:
- 停止主、备 Broker
- 确保主、备 CommitLog 对齐
- 升级后重启
注意:如果主备 CommitLog 不对齐,需要先启动原 Master,再启动原 Slave,否则可能因数据截断丢失消息。
NameServer 集群部署
NameServer 是无状态设计,各节点之间不通信,可以随意扩展。
推荐部署方案
配置客户端连接
// 设置多个 NameServer 地址
producer.setNamesrvAddr("192.168.1.1:9876;192.168.1.2:9876;192.168.1.3:9876");
consumer.setNamesrvAddr("192.168.1.1:9876;192.168.1.2:9876;192.168.1.3:9876");
客户端寻址方式
| 方式 | 说明 | 优缺点 |
|---|---|---|
| 代码指定 | 直接设置 NamesrvAddr | 简单,但修改需重启 |
| 环境变量 | 设置 NAMESRV_ADDR | 灵活,运维方便 |
| HTTP 服务 | 从 HTTP 服务获取 | 最灵活,支持动态更新 |
HTTP 寻址示例:
// 设置 HTTP 寻址地址
System.setProperty("rocketmq.namesrv.domain", "http://namesrv.example.com");
System.setProperty("rocketmq.namesrv.domain.subgroup", "nsaddr");
生产环境部署建议
硬件配置
| 组件 | CPU | 内存 | 磁盘 | 网络 |
|---|---|---|---|---|
| NameServer | 4 核 | 8 GB | 50 GB SSD | 千兆网卡 |
| Broker(Master) | 16 核 | 32 GB | 500 GB+ SSD | 万兆网卡 |
| Broker(Slave) | 16 核 | 32 GB | 500 GB+ SSD | 万兆网卡 |
| Controller | 4 核 | 8 GB | 50 GB SSD | 千兆网卡 |
网络规划
端口规划
| 端口 | 服务 | 说明 |
|---|---|---|
| 9876 | NameServer | 路由服务端口 |
| 10911 | Broker | 客户端连接端口 |
| 10912 | Broker | HA 端口(主从同步) |
| 10909 | Broker | HA 端口(备用) |
| 8081 | Proxy | gRPC 端口 |
| 9877 | Controller | DLedger 端口 |
高可用部署清单
- NameServer 至少部署 2 个节点
- Broker 采用 Master-Slave 架构
- 开启同步刷盘或同步复制
- 配置消息重试和死信队列
- 部署监控系统(Prometheus + Grafana)
- 配置告警规则
- 定期备份配置文件
- 制定故障恢复预案
常见问题
1. Broker 无法注册到 NameServer
问题:Broker 启动后无法注册到 NameServer
排查步骤:
# 检查网络连通性
telnet 192.168.1.1 9876
# 检查 NameServer 是否启动
ps -ef | grep namesrv
# 查看 Broker 日志
tail -f ~/logs/rocketmqlogs/broker.log
解决方案:
- 检查防火墙配置
- 确认 NameServer 地址配置正确
- 检查 Broker 的 brokerIP1 配置
2. 主从同步延迟
问题:Slave 节点同步落后 Master 较多
排查步骤:
# 查看主从同步状态
sh bin/mqadmin brokerStatus -n localhost:9876 -b broker-a
# 查看主从延迟
sh bin/mqadmin clusterList -n localhost:9876
解决方案:
- 检查网络带宽
- 优化磁盘 IO 性能
- 调整 HA 相关参数
3. Controller 选主失败
问题:Controller 集群无法选出 Leader
排查步骤:
# 查看 Controller 日志
tail -f ~/logs/rocketmqlogs/controller.log
# 检查 Raft 节点配置
# 确认 controllerDLegerPeers 配置正确
解决方案:
- 确保多数派节点存活
- 检查节点间网络连通性
- 确认配置参数正确
小结
本章介绍了 RocketMQ 的集群部署方案:
- 单 Master:简单但不可靠,仅用于测试
- 多 Master:高性能但可能丢失消息
- 多 Master 多 Slave:高可用架构,生产环境推荐
- Controller 模式:自动故障转移,RocketMQ 5.x 推荐方案
- 部署建议:硬件、网络、端口规划
选择合适的部署架构是保证消息系统稳定运行的基础。