集群特点
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节点间有毫秒级的消息同步延迟。优缺点如下:
优点:
- 磁盘坏掉,会有少量消息丢失,但是消息的实时性不会受到影响。
- 同时,如果Master宕机,消费者依然可以从Slave节点消费,并且这个转换是透明
的,也无需运维手动介入。 - 性能和多Master模式差不多,弱一点点。
缺点: - 如果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
优缺点如下:
优点:
- 数据和服务都没有单点故障
- 当Master主机宕机,消息的消费不会延迟。
- 服务和数据的高可用。
缺点: - 该模式的性能比异步复制的模式低10%左右。
- 发送消息的延迟稍微高一点。
- 当前版本中,如果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,且不能相同。