前段时间季度OKR任务 RocketMQ 集群的扩展(技术场景调研/文档/实践) 在上个季度已经完成了 清明节放假有时间总结一下 输出一下 从单机到集群的架构和原理探索 最后raft分布式一致性算法进行节点的同步和协作,看了看raft论文和其他分布式算法Paxos论文知识点 也比较有意思,目前只是搭建了3个节点 只能容许一个节点宕机 还是会出现不可用的现象,总比原来的单机好吧. 单机切换到集群过程 怎么切?未消费的数据怎么迁移?后面又遇到节点CPU 100%现象 怎么去解决?Dledger只是当前正好符合我们组内的需求 新的架构模式Controller集群 还是需要花时间去了解。
- 最近在准备jlpt 日语N2考试 lslj4qcpwg.feishu.cn/docx/I4pKdH... ai相关技术都没时间学习 mcp manus等等 RocketMQ源码学习也没有时间了
- RocketMQ 版本迭代是真的快 今天看了一眼已经是5.3.2 版本了 issue和feat也是挺多的。

前期调研 准备
集群方案
- 集群部署的版本确定? 当前部署的单机版本是V4_9_3 rocketmq-4.9.3

单机master ASYNC_MASTER 异步刷盘
单机master broker.conf 配置信息 ASYNC_MASTER 异步刷盘
yaml
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
集群模式
- 多组节点(集群)单副本模式? 一个集群内全部部署 Master 角色,不部署Slave 副本,例如2个Master或者3个Master
- 多节点(集群)多副本模式-异步复制? 每个Master配置一个Slave,有多组 Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级)
- 多节点(集群)多副本模式-同步双写? 每个Master配置一个Slave,有多对 Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功

- 2m-2s-async:2主2从异步刷盘(吞吐量较大,但是消息可能丢失),
- 2m-2s-sync:2主2从同步刷盘(吞吐量会下降,但是消息更安全),
- 2m-noslave:2主无从(单点故障),也可以直接配置broker.conf,进行单点环境配置。
- dleger:是用来实现主从切换的。集群中的节点会基于Raft协议随机选举出一个leader,其他的就都是follower。通常正式环境都会采用这种方式来搭建集群。
macbook pro 本地单机启动 mq
python
wget https://dist.apache.org/repos/dist/release/rocketmq/5.2.0/rocketmq-all-5.2.0-bin-release.zip
unzip rocketmq-all-5.2.0-bin-release.zip
sh ./bin/mqnamesrv
sh bin/mqbroker -n localhost:9876
2主2从异步刷盘的集群
适用于对高可用性有要求,但对消息丢失容忍度较高的场景
- 主从模式中分为Master和Slave两个角色,集群中可以有多个Master节点,一个Master节点可以有多个Slave节点。Master节点负责接收生产者发送的写入请求,将消息写入CommitLog文件,Slave节点会与Master节点建立连接,从Master节点同步消息数据(有同步复制和异步复制两种方式)。消费者可以从Master节点拉取消息,也可以从Slave节点拉取消息。

机器名 | nemaeserver节点部署 | broker 节点部署 |
---|---|---|
25 | nemaeserver | broker-a, broker-b-s |
20 | nemaeserver | broker-b,broker-a-s |
25 机器
bash
nohup ./mqnamesrv &
nohup bin/mqbroker -c conf/2m-2s-async/broker-a.properties &
nohup bin/mqbroker -c conf/2m-2s-async/broker-b-s.properties &
20 机器
bash
nohup ./mqnamesrv &
nohup bin/mqbroker -c conf/2m-2s-async/broker-b.properties &
nohup bin/mqbroker -c conf/2m-2s-async/broker-a-s.properties >nohup2.out 2>&1 &
conf配置文件省略...........
- 关闭2个master节点 测试 剩下两个 slave节点 发送消息直接异常 只有master节点能提供写的功能
sh bin/mqbroker -m 查看配置信息
yaml
2024-10-25 18:02:12 INFO main - namesrvAddr=
2024-10-25 18:02:12 INFO main - listenPort=6888
2024-10-25 18:02:12 INFO main - brokerIP1=xxxxxx
2024-10-25 18:02:12 INFO main - recoverConcurrently=false
2024-10-25 18:02:12 INFO main - autoCreateTopicEnable=true
2024-10-25 18:02:12 INFO main - autoCreateSubscriptionGroup=true
2024-10-25 18:02:12 INFO main - msgTraceTopicName=RMQ_SYS_TRACE_TOPIC
2024-10-25 18:02:12 INFO main - traceTopicEnable=false
2024-10-25 18:02:12 INFO main - rejectTransactionMessage=false
2024-10-25 18:02:12 INFO main - fetchNameSrvAddrByDnsLookup=false
2024-10-25 18:02:12 INFO main - fetchNamesrvAddrByAddressServer=false
2024-10-25 18:02:12 INFO main - transactionTimeOut=6000
2024-10-25 18:02:12 INFO main - transactionCheckMax=15
2024-10-25 18:02:12 INFO main - transactionCheckInterval=30000
2024-10-25 18:02:12 INFO main - aclEnable=false
2024-10-25 18:02:12 INFO main - storePathRootDir=/root/store
2024-10-25 18:02:12 INFO main - storePathCommitLog=
2024-10-25 18:02:12 INFO main - storePathDLedgerCommitLog=
2024-10-25 18:02:12 INFO main - storePathEpochFile=
2024-10-25 18:02:12 INFO main - storePathBrokerIdentity=
2024-10-25 18:02:12 INFO main - disappearTimeAfterStart=-1
2024-10-25 18:02:12 INFO main - storeType=default
2024-10-25 18:02:12 INFO main - flushIntervalCommitLog=500
2024-10-25 18:02:12 INFO main - commitIntervalCommitLog=200
2024-10-25 18:02:12 INFO main - flushCommitLogTimed=true
2024-10-25 18:02:12 INFO main - deleteWhen=04
2024-10-25 18:02:12 INFO main - fileReservedTime=72
2024-10-25 18:02:12 INFO main - deleteFileBatchMax=10
2024-10-25 18:02:12 INFO main - maxTransferBytesOnMessageInMemory=262144
2024-10-25 18:02:12 INFO main - maxTransferCountOnMessageInMemory=32
2024-10-25 18:02:12 INFO main - maxTransferBytesOnMessageInDisk=65536
2024-10-25 18:02:12 INFO main - maxTransferCountOnMessageInDisk=8
2024-10-25 18:02:12 INFO main - accessMessageInMemoryMaxRatio=40
2024-10-25 18:02:12 INFO main - messageIndexEnable=true
2024-10-25 18:02:12 INFO main - messageIndexSafe=false
2024-10-25 18:02:12 INFO main - haMasterAddress=
2024-10-25 18:02:12 INFO main - brokerRole=ASYNC_MASTER
2024-10-25 18:02:12 INFO main - flushDiskType=ASYNC_FLUSH
2024-10-25 18:02:12 INFO main - cleanFileForciblyEnable=true
2024-10-25 18:02:12 INFO main - transientStorePoolEnable=false
2024-10-25 18:02:12 INFO main - dispatchFromSenderThread=false
2024-10-25 18:02:12 INFO main - wakeCommitWhenPutMessage=true
2024-10-25 18:02:12 INFO main - wakeFlushWhenPutMessage=false
2024-10-25 18:02:12 INFO main - enableCleanExpiredOffset=false
2024-10-25 18:02:12 INFO main - totalReplicas=1
2024-10-25 18:02:12 INFO main - inSyncReplicas=1
2024-10-25 18:02:12 INFO main - minInSyncReplicas=1
2024-10-25 18:02:12 INFO main - allAckInSyncStateSet=false
2024-10-25 18:02:12 INFO main - enableAutoInSyncReplicas=false
2024-10-25 18:02:12 INFO main - haFlowControlEnable=false
- 缺点: master提供读写 slave只有备份的功能/读的功能 当masterdown了之后,从节点不会自动升级为master, slave备份了数据 需要手动进行节点切换(特别恶心 不如直接重启master) 没有自动切换的实现 从节点非常鸡肋 达不到我想到的高可用场景
记得修改JVM 内存大小 xms xmx=2g
bash
nohup ./mqnamesrv &
nohup bin/mqbroker -c conf/2m-2s-async/broker-a.properties &
nohup bin/mqbroker -c conf/2m-2s-async/broker-b-s.properties &


Dledger搭建rokcetMQ高可用集群
适用于金融、电商等对数据一致性和系统可靠性有极高要求的业务场景。 高可用、高性能、高可靠
- 为了解决主从架构下Slave不能自动切换为Master的问题,4.5版本之后提供了DLedger模式,使用Raft算法,如果Master节点出现故障,可以自动从Slave节点中选举出新的Master进行切换。
- RocketMQ-on-DLedger Group 是指一组相同名称的 Broker,至少需要 3 个节点,通过 Raft 自动选举出一个 Leader,其余节点 作为 Follower,并在 Leader 和 Follower 之间复制数据以保证高可用。 RocketMQ-on-DLedger Group 能自动容灾切换,并保证数据一致。 RocketMQ-on-DLedger Group 是可以水平扩展的,也即可以部署任意多个 RocketMQ-on-DLedger Group 同时对外提供服务。

- 在 Dledger 模式下,一条消息会被复制到多个
Broker
节点上,因此同一条消息会出现在多个Broker
中。这与传统的 RocketMQ 主从模式不同,它通过 Raft 协议提供了更强的一致性保障。 - Dledger | RocketMQ
-
- 数据复制:DLedger集群通过raft协 议来保证数据的一致性。在集群中,每个节点都维护一个相同的数据副本,以确保当某个节点出现故障时,数据不会丢失。
- 容错性:DLedger集群具有很高的容错性。即使集群中的部分节点发生故障,只要集群中有大多数节点(即超过半数)仍在正常工作,整个集群将继续提供服务。
- 高可用性:DLedger集群通过负载均衡和热备份等机制,确保在节点故障时能够快速切换到其他正常节点,提高整个系统的可用性。
- 分布式锁:DLedger集群提供分布式锁功能,可以解决分布式系统中的资源争用问题,实现跨节点的资源同步。
- 强一致性:DLedger集群通过使用Raft一致性协议,确保在多个副本节点之间同步数据,保证数据的强一致性。
- 高性能:DLedger集群支持水平扩展,可以通过增加节点来提高系统的吞吐量和存储能力,以满足不断增长的业务需求。
- 节点的部署需要是奇数 比如三台(它能够容忍1台机器down,active的机器是2>3/2 大于半数节点 2台其中一台会自动切换为master) 当2台机器down了 剩下的一台不会自动切换为master 。服务器成本问题 3台估计是能接受的极限了,高可用只能接受一台机器down 其他down 自动等重启/恢复 重新选举master
- 相对于2m-2s-async 自动切换是最大的特点
存在问题
- 根据Raft算法的多数原则,集群至少有三个节点以上,在消息写入时,也需要大多数的Follower节点响应成功才能认为消息写入成功;
- Dledger模式下,进行消息写入的时候,使用的是openmessaging包中提供的接口,无法利用RocketMQ原生的存储和复制能力(比如非Dledger模式下使用暂存池方式写入);
- 存在两套日志复制流程(主从模式下一套、Dledger模式下一套),不统一;
深入理解架构原理
5.X 版本 Controller 集群主从模式 主节点down 从节点能够自动切换
- github.com/apache/rock...
- github.com/apache/rock...
- github.com/apache/rock...
- 为了解决如上问题,RocketMQ 5.0以后推出了Controller模式,它的特点如下:
-
- 在主从部署模式下就具有自动切换Master的能力,5.0之前需要使用DLedger才可以;
- 可以利用RocketMQ原生存储复制能力,并统一RocketMQ的存储和复制能力;
真的 没有什么是加一层解决不了的
RocketMQ 5.0对Broker选主相关的功能进行了抽离,放在Controller中,实现了在主从部署模式下就可以自动切换Master,Controller可以独立部署也可以嵌入在NameServer中部署。
独立部署下的Controller

嵌入NameServer中的部署图

Dledger 主要解决 数据一致性 和 高可用性,通过 Raft 协议来保证多个 Broker 之间的数据同步和故障恢复。
Controller 则主要负责 集群管理,包括 Broker 的健康监控、负载均衡、动态扩容等任务。
最终还是选择搭建Dledger集群 相对master-slave组有failover能力。相对controller模式部署更简单。
线上RocketMQ Dledger切换
-
老的单机MQ不要动 新搭建一个Dledger集群 (三台机器) 本来想和ES放在一个机器上 看了下配置 算了 2核3G
-
配置文件格式代码上线 先用单机
-
先试CN数据中心 进行切换 业务消息很少 没有数据堆积问题 直接切(容忍个位数的未消费数据丢失)
-
cat /proc/cpuinfo 2核 8g机器 三台
- broker-n0.conf
- broker-n1.conf
- broker-n2.conf
broker-n0.conf
ini
brokerClusterName = RaftCluster
brokerName=RaftNode00
namesrvAddr=xxxxxxx:9876
storePathRootDir=/root/rocketmq/rmqstore/node00
storePathCommitLog=/root/rocketmq/rmqstore/node00/commitlog
storePathConsumeQueue=/root/rocketmq/storeDledger/consumequeue
storePathIndex=/root/rocketmq/storeDledger/index
storeCheckpoint=/root/rocketmq/storeDledger/checkpoint
abortFile=/root/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-xxx:40911;n1-xxx:40911;n2-xxx:40911
## must be unique
dLegerSelfId=n0
sendMessageThreadPoolNums=4
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerIP1=xxxx
brokerIP2=xxxx
执行启动命令
bash
nohup sh bin/mqnamesrv > nohubNameserv &
nohup sh bin/mqbroker > nohubBroker -c conf/dledger/broker-n0.conf &
broker-n1.conf
ini
brokerClusterName = RaftCluster
brokerName=RaftNode00
namesrvAddr=xxx:9876
storePathRootDir=/root/rocketmq/rmqstore/node01
storePathCommitLog=/root/rocketmq/rmqstore/node01/commitlog
storePathConsumeQueue=/root/rocketmq/storeDledger/consumequeue
storePathIndex=/root/rocketmq/storeDledger/index
storeCheckpoint=/root/rocketmq/storeDledger/checkpoint
abortFile=/root/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-xxx:40911;n1-xxx:40911;n2-xxx:40911
## must be unique
dLegerSelfId=n1
sendMessageThreadPoolNums=4
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
brokerIP1=xxx
brokerIP2=xxx
bash
nohup sh bin/mqnamesrv > nohubNameserv &
nohup sh bin/mqbroker > nohubBroker -c conf/dledger/broker-n1.conf &
broker-n2.conf
ini
brokerClusterName = RaftCluster
brokerName=RaftNode00
namesrvAddr=xxx:9876
storePathRootDir=/root/rocketmq/rmqstore/node02
storePathCommitLog=/root/rocketmq/rmqstore/node02/commitlog
storePathConsumeQueue=/root/rocketmq/storeDledger/consumequeue
storePathIndex=/root/rocketmq/storeDledger/index
storeCheckpoint=/root/rocketmq/storeDledger/checkpoint
abortFile=/root/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-xxx;n1-xxx:40911;n2-xxx:40911
## must be unique
dLegerSelfId=n2
sendMessageThreadPoolNums=4
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
brokerIP1=xxx
brokerIP2=xxx
bash
nohup sh bin/mqnamesrv > nohubNameserv &
nohup sh bin/mqbroker > nohubBroker -c conf/dledger/broker-n2.conf &
sh bin/mqshutdown broker
Broker 节点杀掉命令 sh bin/mqshutdown broker
RocketMQ 4.9.3 Deleger 高可用集群模式 CPU 使用率过高
-
rocketmq 版本:4.9.3 集群模式:deleger 1master 2slave
-
问题现象: 在三台机器都正常的情况下,master所在的机器 会一直有两个broker 线程占用 100% CPU,将master kill 后,重新选举出来的master同样会出现这个问题,kill 2个slave 节点 ,master 上的此问题消失





切换高版本RocketMQ 5.x Dledger解决问题
yaml
wget https://dist.apache.org/repos/dist/release/rocketmq/5.2.0/rocketmq-all-5.2.0-bin-release.zip
unzip rocketmq-all-5.2.0-bin-release.zip
sh ./bin/mqnamesrv
sh bin/mqbroker -n localhost:9876

参考
- 部署方式 | RocketMQ
- RocketMq单机和集群搭建教程_rocketmq4.9.7-CSDN博客
- blog.csdn.net/zk616123/ar...
- rocketmq.apache.org/zh/docs/4.x...
- rocketMQ启动时出现 找不到或无法加载主类 org.apache.rocketmq.namesrv.NamesrvStartup_错误: 找不到或无法加载主类 org.apache.rocketmq.namesrv.namesrv-CSDN博客
- 主备自动切换模式部署 | RocketMQ
- 【RocketMQ】RocketMQ 5.0新特性(三)- Controller模式_rocketmq controller-CSDN博客
- Rocketmq 5.1.0 controller高可用部署实战_rocketmq controller部署视频-CSDN博客
- 2、RocketMQ 2主2从异步刷盘集群搭建_rocketmq 双主双从异步搭建-CSDN博客
- 部署rocketmq集群(2主2从异步)_rocketmq双主双从异步部署-CSDN博客
- RocketMQ双主双从同步集群部署-腾讯云开发者社区-腾讯云
- RocketMQ集群 双主双从同步模式(2m-2s-sync)搭建_wx5bcd2f496a1cf的技术博客_51CTO博客
- juejin.cn/post/684490...