主备自动切换模式部署
背景
当前 RocketMQ Raft 模式主要是利用 DLedger Commitlog 替换原来的 Commitlog,使 Commitlog 拥有选举复制能力,但这也造成了一些问题:
- Raft 模式下,Broker组内副本数必须是三副本及以上,副本的ACK也必须遵循多数派协议。
- RocketMQ 存在两套 HA 复制流程,且 Raft 模式下的复制无法利用 RocketMQ 原生的存储能力。
因此我们希望利用 DLedger 实现一个基于 Raft 的一致性模块(DLedger Controller),并当作一个可选的选主组件,支持独立部署,也可以嵌入在 Nameserver 中,Broker 通过与 Controller 的交互完成 Master 的选举,从而解决上述问题,我们将该新模式称为 Controller 模式。
架构
核心思想
如图是 Controller 模式的核心架构,介绍如下:
- DledgerController:利⽤ DLedger ,构建⼀个保证元数据强⼀致性的 DLedger Controller 控制器,利⽤ Raft 选举会选出⼀个 Active DLedger Controller 作为主控制器,DLedger Controller 可以内嵌在 Nameserver中,也可以独立的部署。其主要作用是,用来存储和管理 Broker 的 SyncStateSet 列表,并在某个 Broker 的 Master Broker 下线或⽹络隔离时,主动发出调度指令来切换 Broker 的 Master。
- SyncStateSet:主要表示⼀个 broker 副本组中跟上 Master 的 Slave 副本加上 Master 的集合。主要判断标准是 Master 和 Slave 之间的差距。当 Master 下线时,我们会从 SyncStateSet 列表中选出新的 Master。 SyncStateSet 列表的变更主要由 Master Broker 发起。Master通过定时任务判断和同步过程中完成 SyncStateSet 的Shrink 和 Expand,并向选举组件 Controller 发起 Alter SyncStateSet 请求。
- AutoSwitchHAService:一个新的 HAService,在 DefaultHAService 的基础上,支持 BrokerRole 的切换,支持 Master 和 Slave 之间互相转换 (在 Controller 的控制下) 。此外,该 HAService 统一了日志复制流程,会在 HA HandShake 阶段进行日志的截断。
- ReplicasManager:作为一个中间组件,起到承上启下的作用。对上,可以定期同步来自 Controller 的控制指令,对下,可以定期监控 HAService 的状态,并在合适的时间修改 SyncStateSet。ReplicasManager 会定期同步 Controller 中关于该 Broker 的元数据,当 Controller 选举出一个新的 Master 的时候,ReplicasManager 能够感知到元数据的变化,并进行 BrokerRole 的切换。
DLedgerController 核心设计
如图是 DledgerController 的核心设计:
- DLedgerController 可以内嵌在 Namesrv 中,也可以独立的部署。
- Active DLedgerController 是 DLedger 选举出来的 Leader,其会接受来自客户端的事件请求,并通过 DLedger 发起共识,最后应用到内存元数据状态机中。
- Not Active DLedgerController,也即 Follower 角色,其会通过 DLedger 复制来自 Active DLedgerController 的事件日志,然后直接运用到状态机中。
构建集群环境准备
该集群至少三台服务器
服务器说明:(生产中应该将 NameServer 部署到其他服务器中,在这为了方便,与Broker部署在一起)
服务器角色 |
IP地址 |
安装的服务 |
服务器1 |
192.168.0.73 |
DLedger,Broker,NameServer |
服务器2 |
192.168.0.74 |
DLedger,Broker,NameServer |
服务器3 |
192.168.0.75 |
DLedger,Broker,NameServer |
Controller 部署
Controller 部署有两种方式。一种是嵌入于 NameServer 进行部署,可以通过配置 enableControllerInNamesrv 打开(可以选择性打开,并不强制要求每一台 NameServer 都打开),在该模式下,NameServer 本身能力仍然是无状态的,也就是内嵌模式下若 NameServer 挂掉多数派,只影响切换能力,不影响原来路由获取等功能。另一种是独立部署,需要单独部署 Controller 组件。
Controller 嵌入 NameServer 部署
安装Java环境
yum install -y java-1.8.0-openjdk java-devel
下载RocketMQ5.0
wget https://dlcdn.apache.org/rocketmq/5.0.0/rocketmq-all-5.0.0-bin-release.zip
下载完成后解压到本地
unzip rocketmq-all-5.0.0-bin-release.zip
创建数据存储目录:
cd rocketmq-all-5.0.0-bin-release mkdir -p rmqstore/commitlog rmqstore/consumequeue rmqstore/index
-
commitlog:生产者投递到rocketmq的数据所存储的目录
-
consumequeue:存储offset数据,用于对commitlog的数据进行索引
-
index:随机读时用到的索引文件
修改日志配置文件:
mkdir logs sed -i 's#${user.home}#/opt/rocketmq#g' conf/*.xml
嵌入 NameServer 部署时只需要在 NameServer 的配置文件中设置 enableControllerInNamesrv=true,并填上 Controller 的配置即可。
服务器1配置
# 文件名 conf/controller/cluster-3n-namesrv-plugin/namesrv-n0.conf #Namesrv config listenPort = 9876 enableControllerInNamesrv = true #controller config controllerDLegerGroup = group1 controllerDLegerPeers = n0-192.168.0.73:9878;n1-192.168.0.74:9878;n2-192.168.0.75:9878 controllerDLegerSelfId = n0 controllerStorePath = /data/rocketmq/rmqstore/DledgerController
服务器2配置
# 文件名 conf/controller/cluster-3n-namesrv-plugin/namesrv-n1.conf #Namesrv config listenPort = 9876 enableControllerInNamesrv = true #controller config controllerDLegerGroup = group1 controllerDLegerPeers = n0-192.168.0.73:9878;n1-192.168.0.74:9878;n2-192.168.0.75:9878 controllerDLegerSelfId = n1 controllerStorePath = /data/rocketmq/rmqstore/DledgerController
服务器3配置
# 文件名 conf/controller/cluster-3n-namesrv-plugin/namesrv-n2.conf #Namesrv config listenPort = 9876 enableControllerInNamesrv = true #controller config controllerDLegerGroup = group1 controllerDLegerPeers = n0-192.168.0.73:9878;n1-192.168.0.74:9878;n2-192.168.0.75:9878 controllerDLegerSelfId = n2 controllerStorePath = /data/rocketmq/rmqstore/DledgerController
参数解释:
- 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 mqnamesrv -c /opt/rocketmq/conf/controller/cluster-3n-namesrv-plugin/namesrv-n0.conf >/dev/null 2>&1 & nohup sh mqnamesrv -c /opt/rocketmq/conf/controller/cluster-3n-namesrv-plugin/namesrv-n1.conf >/dev/null 2>&1 & nohup sh mqnamesrv -c /opt/rocketmq/conf/controller/cluster-3n-namesrv-plugin/namesrv-n2.conf >/dev/null 2>&1 &
Broker 部署
文件位置 conf/dledger/broker-n0.conf
服务器1配置
## 集群名 brokerClusterName = Salary-RaftCluster ## broker组名,同一个RaftClusterGroup内,brokerName名要一样 brokerName=RaftNode00 ## 监听的端口 listenPort=30911 ## 你设置的NameServer地址和端口 namesrvAddr=192.168.0.73:9876;192.168.0.74:9876;192.168.0.75:9876 storePathRootDir=/opt/rocketmq/rmqstore/node00 storePathCommitLog=/opt/rocketmq/rmqstore/node00/commitlog enableDLegerCommitLog=true dLegerGroup=RaftNode00 ## n0 n1 n2 分别是broker1,broker2,broker3 的 dLegerSelfId ## 例如:dLegerPeers=n0-服务器1的IP:40911;n1-服务器2的IP:40912;n2-服务器3的IP:40913 dLegerPeers=n0-192.168.0.73:40911;n1-192.168.0.74:40912;n2-192.168.0.75:40913 ## must be unique ## 这个值必须是在同一个RaftClusterGroup内唯一的 dLegerSelfId=n0 sendMessageThreadPoolNums=16 ## 由于我的虚拟机配置了多个网卡,所以会绑定ip错误,因此我配置了这项, brokerIP1=192.168.0.73
服务器2配置
## 集群名 brokerClusterName = Salary-RaftCluster ## broker组名,同一个RaftClusterGroup内,brokerName名要一样 brokerName=RaftNode00 ## 监听的端口 listenPort=30911 ## 你设置的NameServer地址和端口 namesrvAddr=192.168.0.73:9876;192.168.0.74:9876;192.168.0.75:9876 storePathRootDir=/opt/rocketmq/rmqstore/node01 storePathCommitLog=/opt/rocketmq/rmqstore/node01/commitlog enableDLegerCommitLog=true dLegerGroup=RaftNode00 ## n0 n1 n2 分别是broker1,broker2,broker3 的 dLegerSelfId ## 例如:dLegerPeers=n0-服务器1的IP:40911;n1-服务器2的IP:40912;n2-服务器3的IP:40913 dLegerPeers=n0-192.168.0.73:40911;n1-192.168.0.74:40912;n2-192.168.0.75:40913 ## must be unique ## 这个值必须是在同一个RaftClusterGroup内唯一的 dLegerSelfId=n1 sendMessageThreadPoolNums=16 ## 由于我的虚拟机配置了多个网卡,所以会绑定ip错误,因此我配置了这项, brokerIP1=192.168.0.74
服务器3配置
## 集群名 brokerClusterName = Salary-RaftCluster ## broker组名,同一个RaftClusterGroup内,brokerName名要一样 brokerName=RaftNode00 ## 监听的端口 listenPort=30911 ## 你设置的NameServer地址和端口 namesrvAddr=192.168.0.73:9876;192.168.0.74:9876;192.168.0.75:9876 storePathRootDir=/opt/rocketmq/rmqstore/node02 storePathCommitLog=/opt/rocketmq/rmqstore/node02/commitlog enableDLegerCommitLog=true dLegerGroup=RaftNode00 ## n0 n1 n2 分别是broker1,broker2,broker3 的 dLegerSelfId ## 例如:dLegerPeers=n0-服务器1的IP:40911;n1-服务器2的IP:40912;n2-服务器3的IP:40913 dLegerPeers=n0-192.168.0.73:40911;n1-192.168.0.74:40912;n2-192.168.0.75:40913 ## must be unique ## 这个值必须是在同一个RaftClusterGroup内唯一的 dLegerSelfId=n2 sendMessageThreadPoolNums=16 ## 由于我的虚拟机配置了多个网卡,所以会绑定ip错误,因此我配置了这项, brokerIP1=192.168.0.75
配置完成启动broker
nohup sh mqbroker -c /opt/rocketmq/conf/dledger/broker-n0.conf >/dev/null 2>&1 & nohup sh mqbroker -c /opt/rocketmq/conf/dledger/broker-n1.conf >/dev/null 2>&1 & nohup sh mqbroker -c /opt/rocketmq/conf/dledger/broker-n2.conf >/dev/null 2>&1 &
部署rocketmq- dashboard
docker run -d --name rocketmq-dashboard -e "JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.0.73:9876;192.168.0.74:9876;192.168.0.75:9876" -p 8080:8080 -t apacherocketmq/rocketmq-dashboard:latest
dashboard地址:IP:8080
四、工具测试消息收发
在进行工具测试消息收发之前,我们需要告诉客户端NameServer的地址,RocketMQ有多种方式在客户端中设置NameServer地址,这里我们利用环境变量
NAMESRV_ADDR
$ export NAMESRV_ADDR=localhost:9876
$ sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
SendResult [sendStatus=SEND_OK, msgId= ...
$ sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
ConsumeMessageThread_%d Receive New Messages: [MessageExt...
参考文档:
https://github.com/apache/rocketmq/blob/develop/docs/cn/controller/design.md
https://rocketmq.apache.org/zh/docs/deploymentOperations/03autofailover/#controller-%E9%83%A8%E7%BD%B2
https://rocketmq.apache.org/zh/docs/4.x/bestPractice/02dledger/
如无特殊说明,文章均为本站原创,转载请注明出处
- 转载请注明来源:RocketMQ5.0主备自动切换模式部署
- 本文永久链接地址:https://www.xionghaier.cn/archives/1327.html