MQ高级(四)MQ集群

一、集群分类

RabbitMQ的是基于Erlang语言编写,而Erlang又是一个面向并发的语言,天然支持集群模式。

RabbitMQ的集群有两种模式:

(1)普通集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力。

(2)镜像集群:是一种主从集群,普通集群的基础上,添加了主从备份功能,提高集群的数据可用性。

镜像集群虽然支持主从,但主从同步并不是强一致的,某些情况下可能有数据丢失的风险。因此在 RabbitMQ 的 3.8 版本以后,推出了新的功能:仲裁队列来代替镜像集群,底层采用Raft 协议确保主从的数据一致性。

二、普通集群

普通集群,或者叫标准集群(classic cluster),具备下列特征:

(1)会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。

(2)当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回 (3)队列所在节点宕机,队列中的消息就会丢失MQ高级(四)MQ集群_第1张图片

1. 集群部署

我们先来看普通模式集群,我们的计划部署3节点的mq集群:

MQ高级(四)MQ集群_第2张图片

集群中的节点标示默认都是:`rabbit@[hostname]`,因此以上三个节点的名称分别为:

(1)rabbit@mq1

(2)rabbit@mq2

(3)rabbit@mq3

2.获取cookie

RabbitMQ 底层依赖于 Erlang,而 Erlang 虚拟机就是一个面向分布式的语言,默认就支持集群模式。集群模式中的每个 RabbitMQ 节点使用 cookie 来确定它们是否被允许相互通信。

要使两个节点能够通信,它们必须具有相同的共享秘密,称为 Erlang cookie。cookie 只是一串最多 255 个字符的字母数字字符。

每个集群节点必须具有相同的 cookie。实例之间也需要它来相互通信。

我们先在之前启动的mq容器中获取一个cookie值,作为集群的cookie。执行下面的命令:

docker exec -it mq cat /var/lib/rabbitmq/.erlang.cookie

接下来,停止并删除当前的mq容器,我们重新搭建集群。

docker rm -f mq

3. 准备集群配置

在/tmp目录新建一个配置文件 rabbitmq.conf:

cd /tmp
# 创建文件
touch rabbitmq.conf

文件内容如下:

loopback_users.guest = false
listeners.tcp.default = 5672
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@mq1
cluster_formation.classic_config.nodes.2 = rabbit@mq2
cluster_formation.classic_config.nodes.3 = rabbit@mq3

再创建一个文件,记录cookie

cd /tmp
# 创建cookie文件
touch .erlang.cookie
# 写入cookie
echo "FXZMCVGLBIXZCDEMMVZQ" > .erlang.cookie
# 修改cookie文件的权限
chmod 600 .erlang.cookie

准备三个目录,mq1、mq2、mq3:

cd /tmp
# 创建目录
mkdir mq1 mq2 mq3

然后拷贝rabbitmq.conf、cookie文件到mq1、mq2、mq3:

# 进入/tmp
cd /tmp
# 拷贝
cp rabbitmq.conf mq1
cp rabbitmq.conf mq2
cp rabbitmq.conf mq3
cp .erlang.cookie mq1
cp .erlang.cookie mq2
cp .erlang.cookie mq3

4. 启动集群

创建一个网络:

docker network create mq-net

运行命令

docker run -d --net mq-net \
-v ${PWD}/mq1/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq1 \
--hostname mq1 \
-p 8071:5672 \
-p 8081:15672 \
rabbitmq:3.8-management
docker run -d --net mq-net \
-v ${PWD}/mq2/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq2 \
--hostname mq2 \
-p 8072:5672 \
-p 8082:15672 \
rabbitmq:3.8-management
docker run -d --net mq-net \
-v ${PWD}/mq3/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq3 \
--hostname mq3 \
-p 8073:5672 \
-p 8083:15672 \
rabbitmq:3.8-management

三、镜像集群

镜像集群:本质是主从模式,具备下面的特征:

(1)交换机、队列、队列中的消息会在各个mq的镜像节点之间同步备份。

(2)创建队列的节点被称为该队列的主节点,备份到的其它节点叫做该队列的镜像节点

(3)一个队列的主节点可能是另一个队列的镜像节点

(4)所有操作都是主节点完成,然后同步给镜像节点

(5)主宕机后,镜像节点会替代成新的主

MQ高级(四)MQ集群_第3张图片

 

镜像模式的配置有3种模式:

MQ高级(四)MQ集群_第4张图片

 

3.1 exactly模式

rabbitmqctl set_policy ha-two "^two\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

(1)rabbitmqctl set_policy:固定写法

(2)a-two:策略名称,自定义

(3)"^two\.":匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以`two.`开头的队列名称

(4)'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}':策略内容

1️⃣"ha-mode":"exactly":策略模式,此处是exactly模式,指定副本数量

2️⃣"ha-params":2:策略参数,这里是2,就是副本数量为2,1主1镜像

3️⃣"ha-sync-mode":"automatic":同步策略,默认是manual,即新加入的镜像节点不会同步旧的消息。如果设置为automatic,则新加入的镜像节点会把主节点中所有消息都同步,会带来额外的网络开销

3.2 all模式

rabbitmqctl set_policy ha-all "^all\." '{"ha-mode":"all"}'

(1)ha-all:策略名称,自定义

(2)"^all\.":匹配所有以`all.`开头的队列名

(3)'{"ha-mode":"all"}':策略内容

1️⃣"ha-mode":"all":策略模式,此处是all模式,即所有节点都会称为镜像节点

3.3 nodes模式

rabbitmqctl set_policy ha-nodes "^nodes\." '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'

(1)rabbitmqctl set_policy:固定写法

(2)ha-nodes:策略名称,自定义

(3)"^nodes\.":匹配队列的正则表达式,符合命名规则的队列才生效,这里是任何以`nodes.`开头的队列名称

1️⃣'{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}':策略内容

2️⃣"ha-mode":"nodes":策略模式,此处是nodes模式

3️⃣"ha-params":["rabbit@mq1", "rabbit@mq2"]:策略参数,这里指定副本所在节点名称

四、仲裁队列

仲裁队列:仲裁队列是3.8版本以后才有的新功能,用来替代镜像队列,具备下列特征:

(1)与镜像队列一样,都是主从模式,支持主从数据同步 使

(2)用非常简单,没有复杂的配置

(3)主从同步基于Raft协议,强一致

1. 添加仲裁队列

在任意控制台添加一个队列,一定要选择队列类型为Quorum类型。

MQ高级(四)MQ集群_第5张图片

 

2. SpringAMQP

SpringAMQP创建仲裁队列:

@Configuration
public class QuorumConfig {

    @Bean
    public Queue quorumQueue() {
        return QueueBuilder
                .durable("quorum.queue2") // 持久化
                .quorum() // 仲裁队列
                .build();
    }
}

SpringAMQP连接集群,只需要在yaml中配置即可:

spring:
  rabbitmq:
#    host: 192.168.150.101 # rabbitMQ的ip地址
#    port: 5672 # 端口
    addresses: 192.168.150.101:8071, 192.168.150.101:8072, 192.168.150.101:8073
    username: itcast
    password: 123321
    virtual-host: /

你可能感兴趣的:(黑马【微服务技术栈】,java,服务器,linux)