【RocketMQ系列】RocketMQ集群,RocketMQ-on-DLedger集群

2020-12-02 15:59:28 浏览数 (1)

本文RocketMQ系列第四篇,主要介绍RocketMQ集群及如何部署自动容灾切换的 RocketMQ-on-DLedger Group。

RocketMQ集群搭建

ROcketMQ集群搭建有以下几种方案:

  • 「单Master模式」
  • 「多Master模式」
  • 「多Master多Slave模式-异步复制」
  • 「多Master多Slave模式-同步双写」

其中,

「单Master模式」风险较大,「一旦Broker重启或者宕机时,会导致整个服务不可用」。不建议线上环境使用,可以用于本地测试。

「多Master模式」,一个集群无Slave,全是Master,单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,「消息实时性会受到影响」

「多Master-Slave异步复制模式」,即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时「Master宕机后,消费者仍然可以从Slave消费」,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样。Master宕机会丢失少量的信息。

「多Master-Slave同步双写模式」,数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高,「性能比异步复制模式略低」(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。

我们采用多Master多Slave的异步复制模式来搭建RocketMQ集群。

双主双从集群搭建

1. 在一台虚拟机上安装RocketMQ

在RocketMQ入坑系列第一篇中,已经有安装方法了,很简单,这里不再赘述。

【RocketMQ系列】RocketMQ中的角色详解及实操基本使用

2. 设置配置文件

先在一台虚拟机上操作,设置好配置文件,然后在根据该虚拟机克隆出几台主机出来。

「进入配置文件目录」

cd /usr/local/rocketmq/conf && ll

可以看到

「搭建两主两从异步复制broker集群,进入2m-2s-async目录」

修改「第一组broker的主节点」配置文件broker-a.properties

代码语言:javascript复制
brokerClusterName=RocketMQCluster
brokerName=broker-a
brokerId=0
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH

namesrvAddr=192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876

修改「第一组broker的从节点」配置文件broker-a-s.properties

代码语言:javascript复制
brokerClusterName=RocketMQCluster
brokerName=broker-a
brokerId=1
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH

namesrvAddr=192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876

第二组broker的主从配置文件如法炮制即可。

3. 关键配置项

「namesrvAddr」:nameserver的IP地址,多个IP地址用分号隔开。

「brokerClusterName」:broker集群的名称,这个是整个broker集群的名称,而不是每个主从broker组的名称。同一个集群中,brokerClusterName需一致。

「brokerName」:这个是每个主从broker组的名称,一个master可以有多个slave,但是一个slave只能对应一个master,并且同一master-slave组中他们的brokerName相同。

「brokerId」:同一master-slave组中用brokerId来区分主从,brokerId=0是主节点master,大于1的是从节点。

「deleteWhen」:过期文件真正删除时间。

「fileReservedTime」:Commitlog、ConsumeQueue文件,如果非当前写文件在一定时间间隔内没有再次被更新,则认为是过期文件,可以被删除,RocketMQ不会管这个这个文件上的消息是否被全部消费。

「brokerRole」:Broker的角色。

「flushDiskType」:刷盘方式。

4. 克隆其他三台虚拟机

修改完成后,关闭虚拟机,在克隆出3台虚拟机出来,并修改IP地址和主机名称。

最终RocketMQ集群主机:

5. 启动集群
5.1 启动nameserver

在四台虚拟机上均执行:

代码语言:javascript复制
### 首先启动Name Server,进入$ROCKETMQ_HOME/bin目录后执行
$ nohup sh mqnamesrv &
 
### 验证Name Server 是否启动成功
$ tail -f ~/logs/rocketmqlogs/namesrv.log
The Name Server boot success...

为方便(其实是渣电脑不允许开那么多虚拟机。。。),nameserver就在四台主机上启动了,从刚才的配置文件也能看得出:

代码语言:javascript复制
namesrvAddr=192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876

NameServer实例时间互不通信,这本身也是RocketMQ的设计亮点之一,即允许不同NameServer之间数据不同步。

5.2 启动broker

「192.168.2.170」,启动「broker-a」的Master(在RocketMQ安装目录的bin目录下操作)

代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties &

「192.168.2.171」,启动「broker-b」的Master

代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties &

「192.168.2.172」,启动「broker-a」的Slave

代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties &

「192.168.2.173」,启动「broker-b」的Slave

代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties &

这样集群就启动成功了。

RocketMQ-Console

为了能够方便的查看RocketMQ的集群状态,我们安装一下RocketMQ-Console。

在之前的文章中已经介绍并使用过Docker安装RocketMQ-Console,但是有小伙伴反应自己Docker安装的总是出现问题,这里再提供一下非Docker安装方式:

安装完了后,执行如下命令(比如在192.168.2.170):

代码语言:javascript复制
java -jar rocketmq-console-ng-2.0.0.jar --rocketmq.config.namesrvAddr="192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876"

然后访问:http://192.168.2.170:8080

首页默认显示了nameserver地址。

Cluster信息:

由此证明我们的集群搭建成功了。

集群Master宕机无法进行故障转移

2主2从集群搭建好了,但是这种集群没有容灾能力,也就是说假如一台master挂了,没有办法选举一个新的master出来。

「broker-b」的master(「192.168.2.171」)服务停掉看一下:

「broker-b」的slave节点并不能主动切换成master。

Dledger新集群

能自动容灾的集群才是好集群

在 RocketMQ 4.5 版本之前,RocketMQ 只有 Master/Slave 一种部署方式,一组 broker 中有一个 Master ,有零到多个 Slave,Slave 通过同步复制或异步复制的方式去同步 Master 数据。

这种部署模式,提供了一定的高可用性。但这样的部署模式,有一定的缺陷。比如故障转移方面,如果主节点挂了,还需要人为手动进行重启或者切换,无法自动将一个从节点转换为主节点。

新的多副本架构首先需要解决自动故障转移的问题,本质上来说是「自动选主」的问题。

这个问题的解决方案基本可以分为两种:

  • 利用第三方协调服务集群完成选主,比如 zookeeper 或者 etcd(raft)。这种方案会引入重量级外部组件,加重部署、运维和故障诊断成本,比如在维护 RocketMQ 集群还需要维护 zookeeper 集群,并且 zookeeper 集群故障会影响到 RocketMQ 集群。
  • 利用 raft 协议来完成一个自动选主,raft 协议相比前者的优点是不需要引入外部组件,自动选主逻辑集成到各个节点的进程中,节点之间通过通信就可以完成选主。

RocketMQ选择用 「raft」 协议来解决这个问题,而 「DLedger 就是一个基于 raft 协议的 commitlog 存储库」,也是 RocketMQ 实现新的高可用多副本架构的关键。

Dledger集群搭建

RocketMQ-on-DLedger Group 是指一组「相同名称的 Broker」,至少需要 3 个节点,通过 「Raft」 自动选举出一个 Leader,其余节点作为 Follower,并在 Leader 和 Follower 之间复制数据以保证高可用。

RocketMQ-on-DLedger Group 能自动容灾切换,并保证数据一致。

RocketMQ-on-DLedger Group 是可以水平扩展的,也即可以部署任意多个 RocketMQ-on-DLedger Group 同时对外提供服务。

1. 配置 RocketMQ-on-DLedger Group

上面说到,每组RocketMQ-on-DLedger需要至少3台机器,现在我们在原来的基础上还需要添加2台机器,每组添加一台。

进入dledger配置文件目录下看一眼:

cd /usr/local/rocketmq/conf/dledger && ll

broker-an0节点配置」

代码语言:javascript复制
brokerClusterName = RaftCluster
brokerName=broker-a
listenPort=30911
namesrvAddr=192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876;192.168.2.174:9876;192.168.2.175:9876
storePathRootDir=/tmp/rmqstore/broker-b
storePathCommitLog=/tmp/rmqstore/broker-b/commitlog
enableDLegerCommitLog=true
dLegerGroup=broker-b
dLegerPeers=n0-192.168.2.170:40911;n1-192.168.2.172:40911;n2-192.168.2.174:40911
## must be unique
dLegerSelfId=n0
sendMessageThreadPoolNums=4

broker-a的n1、n2节点配置类似,注意修改dLegerSelfId配置项。

broker-bn0节点配置」

代码语言:javascript复制
brokerClusterName = RaftCluster
brokerName=broker-b
listenPort=30911
namesrvAddr=192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876;192.168.2.174:9876;192.168.2.175:9876
storePathRootDir=/tmp/rmqstore/broker-b
storePathCommitLog=/tmp/rmqstore/broker-b/commitlog
enableDLegerCommitLog=true
dLegerGroup=broker-b
dLegerPeers=n0-192.168.2.171:40911;n1-192.168.2.173:40911;n2-192.168.2.175:40911
## must be unique
dLegerSelfId=n0
sendMessageThreadPoolNums=4

全部配置好以后:

4. 启动集群
4.1 启动nameserver

可以多起几个nameserver,这里我把6台主机的nameserver都起了。

4.2 启动broker

启动命令:

代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/dledger/broker-a-n0.conf

注意配置文件与主机的对应。

4.3 启动控制台查看
代码语言:javascript复制
java -jar rocketmq-console-ng-2.0.0.jar --rocketmq.config.namesrvAddr="192.168.2.170:9876;192.168.2.171:9876;192.168.2.172:9876;192.168.2.173:9876;192.168.2.174:9876;192.168.2.175:9876"
4.4 关闭broker-a的master实例 模拟master宕机
4.5 控制台查看集群

可以看到,新集群自动选举出了一个新的Master。

4.6 重启原来宕机的实例
代码语言:javascript复制
nohup sh mqbroker -c $ROCKETMQ_HOME/conf/dledger/broker-a-n0.conf &
4.7 查看新实例角色

原来的master宕机重启后已经变成了slave。

本次导航结束,以上。


首发公众号 「行百里er」 ,欢迎老铁们关注阅读指正。代码仓库 「GitHub」 github.com/xblzer/JavaJourney

往期推荐

【RocketMQ系列(三)】基于RocketMQ的分布式事务

RocketMQ入坑系列(二)近距离感受RocketMQ如何收发消息

RocketMQ入坑系列(一)角色介绍及基本使用

0 人点赞