RocketMQ集群搭建

集群特点

NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。
每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。

集群模式

单Master模式

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

多Master模式

一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下:
优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高;
缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。

多Master多Slave模式(异步)

每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),这种模式的优缺点如下:
优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样;
缺点:Master宕机,磁盘损坏情况下会丢失少量消息。

多Master多Slave模式(同步)

每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功,这种模式的优缺点如下:
优点:数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高;
缺点:性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。

前置配置

1)安装JDK 11.0.5
2)修改RocketMQ的启动脚本:
bin/runserver.sh
bin/runbroker.sh
bin/tools.sh

bin/runserver.sh文件配置:

#!/bin/sh 

# Licensed to the Apache Software Foundation (ASF) under one or more 
# contributor license agreements. See the NOTICE file distributed with 
# this work for additional information regarding copyright ownership. 
# The ASF licenses this file to You under the Apache License, Version 2.0 
# (the "License"); you may not use this file except in compliance with 
# the License. You may obtain a copy of the License at 
#
# http://www.apache.org/licenses/LICENSE-2.0 
#
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License. 
#==========================================================================
# Java Environment Setting 
#========================================================================== 
error_exit () {
echo "ERROR: $1 !!" 
exit 1 
}

[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 
[ ! -e "$JAVA_HOME/bin/java" ] && error_exit 
"Please set the JAVA_HOME variable in your environment, We need java(x64)!"


export JAVA_HOME 
export JAVA="$JAVA_HOME/bin/java" 
export BASE_DIR=$(dirname $0)/.. export CLASSPATH=.:${BASE_DIR}/conf:${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib/* 

#========================================================================== 
# JVM Configuration 
#==========================================================================

JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m - XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=160m" 
JAVA_OPT="${JAVA_OPT} -XX:CMSInitiatingOccupancyFraction=70 - XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 - XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8" 
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xlog:gc:/dev/shm/rmq_srv_gc.log - XX:+PrintGCDetails" 
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" 
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages" 
#JAVA_OPT="${JAVA_OPT} - Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" 
#JAVA_OPT="${JAVA_OPT} -Xdebug - Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" 
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" 
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 
$JAVA ${JAVA_OPT} $@

bin/runbroker.sh文件配置:

#!/bin/sh 

# Licensed to the Apache Software Foundation (ASF) under one or more 
# contributor license agreements. See the NOTICE file distributed with 
# this work for additional information regarding copyright ownership. 
# The ASF licenses this file to You under the Apache License, Version 2.0 
# (the "License"); you may not use this file except in compliance with 
# the License. You may obtain a copy of the License at 
#
# http://www.apache.org/licenses/LICENSE-2.0 
#
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License. 
#========================================================================== 
# Java Environment Setting 
#========================================================================== 

error_exit () 
{ 
    echo "ERROR: $1 !!" 
    exit 1 
}

[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 
[ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!" 
export JAVA_HOME 
export JAVA="$JAVA_HOME/bin/java" 
export BASE_DIR=$(dirname $0)/..
export CLASSPATH=.${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib/*:${BASE_DIR}/conf:${CL ASSPATH}

#==========================================================================
# JVM Configuration 
#==========================================================================
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m" 
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m - XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 - XX:SoftRefLRUPolicyMSPerMB=0" 
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/mq_gc_%p.log - XX:+PrintGCDetails" 
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" 
JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch" 
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g" 
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking" 
#JAVA_OPT="${JAVA_OPT} -Xdebug - Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" 
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" 
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 

numactl --interleave=all pwd > /dev/null 2>&1 
if [ $? -eq 0 ] 
then
    if [ -z "$RMQ_NUMA_NODE" ] ; then 
        numactl --interleave=all $JAVA ${JAVA_OPT} $@ 
    else
        numactl --cpunodebind=$RMQ_NUMA_NODE --membind=$RMQ_NUMA_NODE $JAVA ${JAVA_OPT} $@ 
    fi else
        $JAVA ${JAVA_OPT} --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED 
$@
fi

bin/tools.sh文件配置:

#!/bin/sh 

# Licensed to the Apache Software Foundation (ASF) under one or more 
# contributor license agreements. See the NOTICE file distributed with 
# this work for additional information regarding copyright ownership. 
# The ASF licenses this file to You under the Apache License, Version 2.0 
# (the "License"); you may not use this file except in compliance with 
# the License. You may obtain a copy of the License at 
#
# http://www.apache.org/licenses/LICENSE-2.0 
#
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License.
#========================================================================== 
# Java Environment Setting 
#========================================================================== 
error_exit () 
{ 
    echo "ERROR: $1 !!" 
    exit 1 
}

[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 
[ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!" 

export JAVA_HOME 
export JAVA="$JAVA_HOME/bin/java" 
export BASE_DIR=$(dirname $0)/.. 
# export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} 
export CLASSPATH=.${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib/*:${BASE_DIR}/conf:${CL ASSPATH} 
#========================================================================== 
# JVM Configuration 
#========================================================================== 
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=128m" 
# JAVA_OPT="${JAVA_OPT} - Djava.ext.dirs=${BASE_DIR}/lib:${JAVA_HOME}/jre/lib/ext" 
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 
$JAVA ${JAVA_OPT} $@

单Master模式配置

这是最简单也是风险最大的模式,一旦broker重启或宕机,整个服务不可用。不推荐在生产环境使用,一般用于开发或本地测试。
步骤如下:

启动NameServer
###首先启动NameServer 
$ nohup sh mqnamesrv & 
###检查Name Server是否启动成功 
$ tail -f ~/logs/rocketmqlogs/namesrv.log 
The Name Server boot success...

只要在namesrv.log中看到“The Name Server boot success.. ”就表示NameServer启动成功了。

启动Broker

###首先启动broker 
$ nohup sh mqbroker -n localhost:9876 &
###检查broker是否启动成功。如果看到broker的下面的语句表示启动成功 
$ tail -f ~/logs/rocketmqlogs/broker.log 
The broker[broker-a,192.169.1.2:10911] boot success...

如果在broker.log中看到“The broker[brokerName,ip:port] boot success..”就表示broker启动成功。

多Master模式

多Master模式意味着所有的节点都是Master节点,没有Slave节点。优缺点如下:
优点:
1)配置简单。
2)一个服务器节点的停用或重启(维护目的)不会对应用造成大的影响。
3)如果磁盘配置了RAID10,就不会由消息的丢失。(因为RAID10非常可靠,即使服
务器不可恢复,在异步刷盘时会丢失小量数据,同步刷盘不会丢数据)。
4)该模式性能最好。
缺点:
1)在单个节点停用期间,消费者无法消费该节点上的数据,也不能订阅该节点上的数据,除非节点恢复。消息的实时性受到影响。
启动步骤如下:

启动NameServer
###首先启动NameServer 
$ nohup sh mqnamesrv & 
###检查NameServer是否启动成功 
$ tail -f ~/logs/rocketmqlogs/namesrv.log 
The Name Server boot success...
启动Broker集群
### 启动第一个broker,假定namesrv在192.168.1.1上。注意这里的配置文件的位置 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m- noslave/broker-a.properties & 
### 在第二台服务器上启动另一个broker。 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m- noslave/broker-b.properties &

上面的NameServer是一台,IP地址直接写,如果是多台NameServer,则需要在 -n 后接多个NameServer的地址,使用分号分开。由于shell对分号敏感,可以使用单引号引起来多个NameServer的地址,禁止shell对分号的解释。

多Master和Slave模式-异步复制

每个Master节点配置一个或多个Slave节点,组成一组,有多组这样的组合组成集群。HA使用异步复制,Master和Slave节点间有毫秒级的消息同步延迟。优缺点如下:
优点:

  1. 磁盘坏掉,会有少量消息丢失,但是消息的实时性不会受到影响。
  2. 同时,如果Master宕机,消费者依然可以从Slave节点消费,并且这个转换是透明
    的,也无需运维手动介入。
  3. 性能和多Master模式差不多,弱一点点。
    缺点:
  4. 如果Master宕机,磁盘坏掉,会丢失少量消息。
    启动步骤如下:
启动NameServer
###首先启动NameServer 
$ nohup sh mqnamesrv & 
###检查NameServer是否启动成功 
$ tail -f ~/logs/rocketmqlogs/namesrv.log 
The Name Server boot success...
启动Broker集群
### 启动Master的broker:broker-a 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- async/broker-a.properties & 
### 在另外一台服务器上启动另一个Master的broker:broker-b 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- async/broker-b.properties & 
### 在另一台服务器上启动broker-a的Slave 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- async/broker-a-s.properties & 
### 在另一台服务器上启动broker-b的Slave 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- async/broker-b-s.properties &

以上启动的是2M-2S-Async模式,双主双从,主从异步复制模式。

多Master和Slave模式-同步双写

该模式中,每个Master节点配置多个Slave节点,它们构成一组,多组构成集群。HA使用同步双写,即,只有消息在Master节点和多个Slave节点上写成功,才返回生产者消息发送成功。
ASYNC_MASTER
SYNC_MASTER
优缺点如下:
优点:

  1. 数据和服务都没有单点故障
  2. 当Master主机宕机,消息的消费不会延迟。
  3. 服务和数据的高可用。
    缺点:
  4. 该模式的性能比异步复制的模式低10%左右。
  5. 发送消息的延迟稍微高一点。
  6. 当前版本中,如果Master节点宕机,Slave节点不能自动切换为Master模式。
    启动步骤如下:
启动NameServer
###首先启动NameServer
$ nohup sh mqnamesrv & 
### 检查NameServer是否启动成功。 
$ tail -f ~/logs/rocketmqlogs/namesrv.log 
The Name Server boot success...
启动Broker集群
### 在一个节点启动broker-a(MASTER) 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- sync/broker-a.properties & 
### 在另一个节点启动broker-b(MASTER) 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- sync/broker-b.properties & 
### 在另一个节点启动broker-a的同步Slave节点:broker-a-s 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- sync/broker-a-s.properties & 
### 在另一个节点启动broker-b的同步Slave节点:broker-b-s 
$ nohup sh mqbroker -n 192.168.1.1:9876 -c $ROCKETMQ_HOME/conf/2m-2s- sync/broker-b-s.properties &

上述配置中,通过相同的brokerName不同的brokerId将Master和Slave组合为一组。Master的brokerId必须是0,Slave的brokerId必须大于0,且不能相同。

你可能感兴趣的:(RocketMQ集群搭建)