主从自动故障转移模式
本文档主要介绍如何部署支持自动主从切换的 RocketMQ 集群。其架构如上图所示,主要增加了支持自动主从切换的 Controller 组件,可以独立部署或嵌入到 NameServer 中。
Controller 部署
Controller 组件提供主节点的选择。如果 Controller 需要容错,则需要部署三个或更多副本(遵循 Raft 多数协议)。
如果 Controller 仅部署为单个副本,它仍然可以完成 Broker 故障转移,但如果单点 Controller 发生故障,它将影响切换能力,但不会影响现有集群的正常发送和接收。
部署 Controller 有两种方式。一种是将其嵌入到 NameServer 中进行部署。这可以通过设置 enableControllerInNamesrv 来打开(可以有选择地打开,并不需要在每个 NameServer 上都打开)。在这种模式下,NameServer 本身仍然是无状态的,这意味着如果 NameServer 在嵌入模式下发生故障,它只会影响切换能力,不会影响原始路由获取和其他功能。另一种是独立部署 Controller 组件。
将 Controller 嵌入到 NameServer 中进行部署
当 Controller 嵌入到 NameServer 中进行部署时,您只需要在 NameServer 配置文件中设置 enableControllerInNamesrv=true
并填写 Controller 配置。
enableControllerInNamesrv = true
controllerDLegerGroup = group1
controllerDLegerPeers = n0-127.0.0.1:9877;n1-127.0.0.1:9878;n2-127.0.0.1:9879
controllerDLegerSelfId = n0
controllerStorePath = /home/admin/DledgerController
enableElectUncleanMaster = false
notifyBrokerRoleChanged = true
参数说明:
- enableControllerInNamesrv: 是否在 Nameserver 中启用 Controller,默认值为 false。
- controllerDLegerGroup: DLedger Raft Group 的名称,在同一个 DLedger Raft Group 中必须一致。
- controllerDLegerPeers: DLedger Group 中节点的端口信息,同一个 Group 中节点的配置必须一致。
- controllerDLegerSelfId: 节点 ID,必须是 controllerDLegerPeers 中的一个;同一个 Group 中的每个节点必须唯一。
- controllerStorePath: Controller 日志存储的位置。Controller 是有状态的,Controller 需要依赖日志在重启或崩溃时恢复数据。这个目录非常重要,不能轻易删除。
- enableElectUncleanMaster: 是否可以从 SyncStateSet 外部选举 Master。如果为 true,可能会选择数据过时的副本作为 Master,并丢失消息。默认值为 false。
- notifyBrokerRoleChanged: Broker 副本组角色发生变化时是否主动通知,默认值为 true。
设置完参数后,您可以通过指定配置文件来启动 Nameserver。
$ nohup sh bin/mqnamesrv -c namesrv.conf &
Controller 独立部署
要独立部署,请运行以下脚本
$ nohup sh bin/mqcontroller -c controller.conf &
mqcontroller 脚本位于源代码包中的 distribution/bin/mqcontroller
,配置参数与嵌入模式相同。
独立部署 Controller 后,您仍然需要单独部署 NameServer 来提供路由发现功能。
Broker 部署
Broker 启动方式与之前相同,增加了以下参数
- enableControllerMode: Broker Controller 模式的总开关。只有当此值为 true 时,才会启用自动主备切换模式。默认值为 false。
- controllerAddr: Controller 的地址,多个 Controller 之间用分号隔开。例如,
controllerAddr = 127.0.0.1:9877;127.0.0.1:9878;127.0.0.1:9879
- syncBrokerMetadataPeriod: 将 Broker 副本信息同步到 Controller 的时间间隔。默认值为 5000(5 秒)。
- checkSyncStateSetPeriod: 检查 SyncStateSet 的时间间隔,检查 SyncStateSet 可能会缩小 SyncState。默认值为 5000(5 秒)。
- syncControllerMetadataPeriod: 同步 Controller 元数据的時間間隔,主要用于获取活动 Controller 的地址。默认值为 10000(10 秒)。
- haMaxTimeSlaveNotCatchup: Slave 未追赶上 Master 的最大时间间隔,如果 SyncStateSet 中的 Slave 超过此时间间隔,它将从 SyncStateSet 中移除。默认值为 15000(15 秒)。
- storePathEpochFile: epoch 文件的位置。epoch 文件非常重要,不能随意删除。默认位于 store 目录中。
- allAckInSyncStateSet: 如果此值为 true,只有当消息已复制到 SyncStateSet 中的每个副本时,才会向客户端返回成功,确保消息不会丢失。默认值为 false。
- syncFromLastFile: 如果 Slave 是空白磁盘启动,是否从最后一个文件复制。默认值为 false。
- asyncLearner: 如果此值为 true,副本将不会进入 SyncStateSet,即它不会被选举为 Master,而是始终充当学习者副本并执行异步复制。默认值为 false。
- inSyncReplicas: 需要保持同步的副本组数量,默认值为 1,当 allAckInSyncStateSet=true 时,此参数无效。
- minInSyncReplicas: 需要保持同步的副本组的最小数量。如果 SyncStateSet 中的副本数量少于 minInSyncReplicas,putMessage 将返回 PutMessageStatus.IN_SYNC_REPLICAS,默认值为 1
在 Controller 模式下,Broker 配置必须设置 enableControllerMode=true 并填写 controllerAddr,并使用以下命令启动
$ nohup sh bin/mqbroker -c broker.conf &
在自动主备切换模式下,Broker 不需要指定 brokerId 和 brokerRole,这些由 Controller 组件分配。
兼容性
此模式不会对任何客户端级别的 API 进行任何更改或修改,并且与客户端没有兼容性问题。
NameServer 本身没有被修改,并且与 NameServer 没有兼容性问题。如果启用了 enableControllerInNamesrv 并正确配置了 Controller 参数,则 Controller 功能将被启用。
如果 Broker 设置为 enableControllerMode=false
,它将继续像以前一样运行。如果 enableControllerMode=true
,则必须部署 Controller 并正确配置参数才能正常运行。
具体行为如以下表格所示
旧的 nameserver | 旧的 nameserver + 独立部署 controllers | 新的 nameserver 启用 controller | 新的 nameserver 禁用 controller | |
---|---|---|---|---|
旧的 broker | 正常运行,无法故障转移 | 正常运行,无法故障转移 | 正常运行,无法故障转移 | 正常运行,无法故障转移 |
新的 broker 启用 controller 模式 | 无法正常上线 | 正常运行,可以故障转移 | 正常运行,可以故障转移 | 无法正常上线 |
新的 broker 禁用 controller 模式 | 正常运行,无法故障转移 | 正常运行,无法故障转移 | 正常运行,无法故障转移 | 正常运行,无法故障转移 |
升级注意事项
从上面的兼容性说明可以看出,NameServer 可以正常升级,没有兼容性问题。在不升级 NameServer 的情况下,可以独立部署 Controller 组件来获得切换功能。对于 Broker 升级,有两种情况
主从部署升级到 Controller 切换架构
可以进行带数据的就地升级。对于每组 Broker,停止主备 Broker,并确保主备的 CommitLogs 对齐(您可以在升级前一段时间禁用对这组 Broker 的写入,或者通过复制来确保一致性)。升级完包后,重启。
注意如果主备 CommitLogs 未对齐,则需要确保主节点在线后备节点才能在线,否则由于数据截断可能会导致消息丢失。
从 DLedger 模式升级到 Controller 切换架构
由于 DLedger 模式和主从模式的消息数据格式不同,因此无法进行带数据的就地升级。在部署多个 Broker 组的情况下,可以考虑在一段时间内(只要确认所有现有消息都被消费)禁用对一组 Broker 的写入,然后升级并部署 Controller 和新的 Broker。这样,新的 Broker 将从现有的 Broker 消费消息,而现有的 Broker 将从新的 Broker 消费消息,直到消费平衡,然后可以停用现有的 Broker。