Apache RocketMQ 自动主从切换(Controller 模式)快速开始指南:一键部署、状态验证与故障切换实践
2026/9/20 15:37:26 网站建设 项目流程

Apache RocketMQ 自动主从切换(Controller 模式)快速开始指南:一键部署、状态验证与故障切换实践

【免费下载链接】rocketmqApache RocketMQ is a cloud native messaging and streaming platform, making it simple to build event-driven applications.项目地址: https://gitcode.com/gh_mirrors/ro/rocketmq

导读

本文基于 Apache RocketMQ 仓库中的 docs/cn/controller/quick_start.md 展开,完整讲解如何快速构建一套具备自动主从切换能力的 RocketMQ 集群:从编译源码、一键启动,到用mqadmin运维命令查看SyncStateSetBrokerEpoch,再到手动 Kill Master 验证故障切换全过程。读完本文,你将掌握 Controller(DLedger 模式)内嵌 NameServer、内嵌 3 节点集群、独立 3 节点集群三种部署形态的实操方法,并能依据 deploy.md 与 design.md 进一步完成生产级新集群部署与旧集群升级。

架构总览:Controller 让“谁当 Master”不再靠人工

在传统 RocketMQ 主从模式下,Master 与 Slave 的角色由brokerId静态决定,Master 故障时需要人工干预(如修改配置、重启或依赖脚本切换),可用性维护成本高。自动主从切换方案的核心是引入一个独立的Controller组件:

  • Controller 负责维护每个 broker 复制组(broker-set)的 SyncStateSet(同步副本集合),并基于多数派(Quorum)协议为集合内副本选举/指派 Master 与 Slave 角色
  • 当 Master 失联后,Controller 会从 SyncStateSet 中自动选出新的 Master,并将角色变更结果通知相关 Broker,实现真正意义上的自动故障转移;
  • Controller 本身基于Raft 类协议(DLedger)组成集群,从而自身具备高可用能力,可以独立部署,也可以内嵌在 NameServer 进程中(通过enableControllerInNamesrv开关开启)。

该架构的详细设计思路见 设计思想,新集群部署与旧集群升级的完整指南见 部署指南。

编译 RocketMQ 源码

在开始部署前,需要先从源码构建发行包:

$ git clone https://github.com/apache/rocketmq.git $ cd rocketmq $ mvn -Prelease-all -DskipTests clean install -U

构建成功后,发行包会被输出到distribution/target/目录下,内含bin/(启动脚本与mqadmin运维工具)与conf/(各类配置文件),后续所有操作都在发行包目录内完成。

快速部署:一条命令拉起“1 Controller + 2 Broker”最小集群

一键启动与停止

进入发行包目录后,直接运行快速启动脚本:

#{rocketmq-version} 替换为 rocketmq 实际版本号,例如 5.0.0-SNAPSHOT $ cd distribution/target/rocketmq-{rocketmq-version}/rocketmq-{rocketmq-version}/ $ sh bin/controller/fast-try.sh start

需要关闭快速集群时执行:

$ sh bin/controller/fast-try.sh stop

从仓库中的脚本实现看,fast-try.sh(distribution/bin/controller/fast-try.sh)实际做了以下事情:

  • startNameserver:以-Xms512m -Xmx512m的 JVM 参数启动bin/mqnamesrv -c ./conf/controller/quick-start/namesrv.conf(该配置开启了enableControllerInNamesrv = true,即 Controller 内嵌在 NameServer 中);
  • startBroker:以-Xms1g -Xmx1g的 JVM 参数依次启动bin/mqbroker -c ./conf/controller/quick-start/broker-n0.confbroker-n1.conf两个 Broker;
  • checkConf:启动前会校验三个配置文件是否齐全,缺失即报错退出。

也就是说,快速部署默认会开启1 个内嵌了 Controller 的 NameServer 和 2 个 Broker。相关默认配置位于conf/controller/quick-start/目录(即仓库中的 distribution/conf/controller/quick-start),存储路径默认为/tmp/rmqstore

默认配置逐项解读

namesrv.conf(distribution/conf/controller/quick-start/namesrv.conf):

enableControllerInNamesrv = true controllerDLegerGroup = group1 controllerDLegerPeers = n0-127.0.0.1:9878 controllerDLegerSelfId = n0
配置项含义
enableControllerInNamesrv是否将 Controller 以插件方式内嵌到 NameServer 进程中,true表示开启
controllerDLegerGroupController 所在的 DLedger Raft 组名称,组内所有节点必须一致
controllerDLegerPeersController 集群全部节点列表,格式为selfId-ip:port,多节点用;分隔
controllerDLegerSelfId当前节点在 Controller 集群中的自 ID,必须与controllerDLegerPeers中的某个selfId对应

broker-n0.confbroker-n1.conf(broker-n0.conf / broker-n1.conf)配置了两个属于同一 broker-set(brokerName = broker-a)的 Broker 节点,端口与存储路径互不相同:

配置项broker-n0broker-n1含义
brokerNamebroker-abroker-a同一复制组内所有副本必须同名
brokerId-1-1-1表示由 Controller 动态分配 ID
brokerRoleSLAVESLAVE启动时均以 SLAVE 身份注册,角色由 Controller 裁决
enableControllerModetruetrue开启 Broker 的 Controller 模式,接受 Controller 的角色管理
controllerAddr127.0.0.1:9878127.0.0.1:9878Controller 地址(快速部署中为内嵌 Controller 的 NameServer 地址)
namesrvAddr127.0.0.1:9876127.0.0.1:9876NameServer 地址
allAckInSyncStateSettruetrue要求消息在 SyncStateSet 内全部副本确认后才返回成功,是自动切换下保证数据一致性的关键
listenPort3091130921Broker 对外服务端口
storePathRootDir/storePathCommitLog/tmp/rmqstore/node00/tmp/rmqstore/node01各自独立的存储路径,避免数据目录冲突

提示:brokerId = -1是 Controller 模式下的典型写法——节点不再自行声明角色,而是由 Controller 在注册与选举流程中动态分配 0(Master)或 1(Slave)等 ID。可对照 ControllerConfig.java 中controllerDLegerGroupcontrollerDLegerPeerscontrollerDLegerSelfId等字段了解其底层承载。

验证 Controller 集群状态

启动成功后,用运维命令查看 Controller 元数据:

$ sh bin/mqadmin getControllerMetaData -a localhost:9878

-a代表集群中任意一个 Controller 的地址。该命令对应仓库中的 GetControllerMetaDataSubCommand.java,会返回 Controller 组的 Leader 信息与全部 Peer 列表。

至此集群启动成功,即可向集群收发消息,并进行下面的切换测试。

查看 SyncStateSet 与 BrokerEpoch

查看 SyncStateSet

SyncStateSet(同步副本集合)记录了当前与 Master 保持同步的副本集合,是 Controller 决策切换的重要依据,可以通过运维工具查看:

$ sh bin/mqadmin getSyncStateSet -a localhost:9878 -b broker-a

-a是任意一个 Controller 的地址,-b是目标 broker-set 名称。命令实现在 GetSyncStateSetSubCommand.java。

如果顺利的话,可以看到类似下图的内容(集合内包含当前 Master 与同步中的 Slave 副本信息):

查看 BrokerEpoch

BrokerEpoch 用于标记每一次 Master 选举的代数,防止旧 Master 复活后产生“双主”脑裂,可通过运维工具查看:

$ sh bin/mqadmin getBrokerEpoch -n localhost:9876 -b broker-a

-n代表任意一个 NameServer 的地址。命令实现在 GetBrokerEpochSubCommand.java。

如果顺利的话,可以看到类似下图的内容(包含 epoch 代数与 master/slave 的 brokerId 记录):

切换验证:Kill 掉 Master,观察自动故障转移

集群部署成功后,即可手动验证自动主从切换能力。

步骤一:定位并 Kill 原 Master

在上文的快速部署中,两个 Broker 的端口分别为 30911(broker-n0)与 30921(broker-n1),其中被 Controller 选为 Master 的是使用端口30911的进程。通过进程过滤命令找到并杀掉它:

# 查找端口: $ ps -ef|grep java|grep BrokerStartup|grep ./conf/controller/quick-start/broker-n0.conf|grep -v grep|awk '{print $2}' # 杀掉 master: $ kill -9 PID

说明:fast-try.shstopBroker实现(见 distribution/bin/controller/fast-try.sh)也使用了类似的ps -ef | grep BrokerStartup | grep <conf> | grep -v grep | awk '{print $2}'模式来按配置定位进程,这里为模拟真实故障直接使用kill -9

步骤二:观察 Master 是否切换

杀掉 Master 后,再次查看 SyncStateSet:

$ sh bin/mqadmin getSyncStateSet -a localhost:9878 -b broker-a

可以发现Master 已经发生了切换——Controller 感知到原 Master 失联(scanNotActiveBrokerInterval默认为 5 秒扫描一次,见 ControllerConfig.java),从 SyncStateSet 中选出新的 Master 并完成角色通知:

整个过程无需人工干预,这即是 Controller 模式相对传统主从模式的核心价值。

Controller 内嵌 NameServer 集群部署(3 节点)

对于生产环境,Controller 需要以多副本集群方式部署以保障自身高可用。第一种形态是Controller 以插件方式内嵌于 NameServer 集群(3 个 Node)

一键启动

$ sh bin/controller/fast-try-namesrv-plugin.sh start

该脚本(fast-try-namesrv-plugin.sh)会依次启动三个 NameServer(内嵌 Controller):

$ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n0.conf & $ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n1.conf & $ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n2.conf &

三个节点的配置位于 distribution/conf/controller/cluster-3n-namesrv-plugin,以namesrv-n0.conf为例:

# Namesrv config listenPort = 9876 enableControllerInNamesrv = true # controller config controllerDLegerGroup = group1 controllerDLegerPeers = n0-127.0.0.1:9878;n1-127.0.0.1:9868;n2-127.0.0.1:9858 controllerDLegerSelfId = n0

其余两节点(n1、n2)仅listenPort(9886/9896)与controllerDLegerSelfId(n1/n2)不同,controllerDLegerPeers必须三节点完全一致,以组成同一个 DLedger Raft 组。

验证 Controller 集群状态

$ sh bin/mqadmin getControllerMetaData -a localhost:9878

-a是任意一个 Controller 的地址。如果 Controller 启动成功,可以看到类似以下内容:

#ControllerGroup group1 #ControllerLeaderId n0 #ControllerLeaderAddress 127.0.0.1:9878 #Peer: n0:127.0.0.1:9878 #Peer: n1:127.0.0.1:9868 #Peer: n2:127.0.0.1:9858

接入 Broker 与停止集群

启动成功后,Broker 以 Controller 模式部署(enableControllerMode = truecontrollerAddr指向任一 Controller 地址)即可使用该 Controller 集群。

需要快速停止集群时:

$ sh bin/controller/fast-try-namesrv-plugin.sh stop

使用fast-try-namesrv-plugin.sh脚本快速部署,默认配置在conf/controller/cluster-3n-namesrv-plugin里面,并且会启动3 个 NameServer 和 3 个 Controller(内嵌于 NameServer)

Controller 独立集群部署(3 节点)

第二种形态是Controller 独立部署,与 NameServer 完全解耦,适合已有 NameServer 集群、仅需新增 Controller 能力的场景。

一键启动

$ sh bin/controller/fast-try-independent-deployment.sh start

该脚本(fast-try-independent-deployment.sh)会启动三个独立 Controller 进程:

$ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n0.conf & $ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n1.conf & $ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n2.conf &

三个节点的配置位于 distribution/conf/controller/cluster-3n-independent,以controller-n0.conf为例:

controllerDLegerGroup = group1 controllerDLegerPeers = n0-127.0.0.1:9878;n1-127.0.0.1:9868;n2-127.0.0.1:9858 controllerDLegerSelfId = n0

mqcontroller启动入口对应仓库中的 ControllerStartup.java,独立模式不再需要enableControllerInNamesrv与 NameServer 的listenPort,仅需配置 DLedger 组信息。

验证 Controller 集群状态

$ sh bin/mqadmin getControllerMetaData -a localhost:9878

如果 Controller 启动成功,可以看到类似以下内容(注意本例中 Leader 为 n1,说明 Leader 由 Raft 选举动态产生,不一定是 n0):

#ControllerGroup group1 #ControllerLeaderId n1 #ControllerLeaderAddress 127.0.0.1:9868 #Peer: n0:127.0.0.1:9878 #Peer: n1:127.0.0.1:9868 #Peer: n2:127.0.0.1:9858

接入 Broker 与停止集群

启动成功后,Broker 以 Controller 模式部署即可使用该 Controller 集群。

需要快速停止集群时:

$ sh bin/controller/fast-try-independent-deployment.sh stop

使用fast-try-independent-deployment.sh脚本快速部署,默认配置在conf/controller/cluster-3n-independent里面,并且会启动3 个独立部署的 Controller 组成一个集群

三种部署形态对比与选型建议

部署形态启动命令进程数配置文件目录适用场景
快速部署(内嵌单点)fast-try.sh start1 NameServer(含 Controller)+ 2 Brokerdistribution/conf/controller/quick-start本地体验、功能验证、开发调试
Controller 内嵌 NameServer 集群fast-try-namesrv-plugin.sh start3 NameServer(各含 Controller)distribution/conf/controller/cluster-3n-namesrv-plugin希望复用 NameServer 进程、减少部署组件数的生产场景
Controller 独立集群fast-try-independent-deployment.sh start3 Controllerdistribution/conf/controller/cluster-3n-independent已有 NameServer 集群、Controller 独立扩缩容的生产场景

三种形态下,Broker 侧的接入方式完全一致:设置enableControllerMode = truecontrollerAddr = <任一Controller地址>,并将brokerId设为-1交由 Controller 动态分配。

注意事项与最佳实践

  • Controller 高可用需要三副本及以上:若需要保证 Controller 具备容错能力,Controller 部署需要三副本及以上(遵循 Raft 的多数派协议,容忍少数节点故障);单副本 Controller 无法在自身故障时继续提供仲裁能力。
  • 多机部署时务必修改controllerDLegerPeers中的 IP:配置参数controllerDLegerPeers中的 IP 地址需要配置成其他节点能够访问的 IP,在多机器部署的时候尤为重要。仓库提供的示例(127.0.0.1)仅供单机快速体验参考,实际部署需根据环境修改调整。
  • allAckInSyncStateSet与数据一致性:快速部署配置中开启了allAckInSyncStateSet=true,要求消息被 SyncStateSet 内全部副本确认后才返回成功,这是保证 Master 切换后不丢消息的关键设置;生产环境可根据容灾与延迟要求权衡。
  • 关注不可用 Master 的选举策略:从 ControllerConfig.java 的源码可以看出,Controller 还支持enableElectUncleanMaster(是否允许选举不在 SyncStateSet 中的 Master,默认false)、electMasterMaxRetryCount(选举失败最大重试次数,默认 3)等高级参数,生产调优时可结合 设计思想 与 部署指南 综合评估。

总结

本文从零完成了 RocketMQ 自动主从切换集群的快速构建与验证:通过fast-try.sh一条命令拉起最小集群,用getControllerMetaDatagetSyncStateSetgetBrokerEpoch三个运维命令确认 Controller 与复制组状态,并通过 Kill Master 实测了自动切换能力;随后给出内嵌 NameServer 与独立部署两种 3 节点生产形态的部署方法。基于这套快速开始流程,配合仓库中的 deploy.md(新集群部署与旧集群升级)与 design.md(架构与选举设计),即可将自动主从切换方案落地到实际生产环境。

【免费下载链接】rocketmqApache RocketMQ is a cloud native messaging and streaming platform, making it simple to build event-driven applications.项目地址: https://gitcode.com/gh_mirrors/ro/rocketmq

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询