一、集群分类
RabbitMQ的是基于Erlang语言编写,而Erlang又是一个面向并发的语言,天然支持集群模式。
RabbitMQ的集群有两种模式:
(1)普通集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力。
(2)镜像集群:是一种主从集群,普通集群的基础上,添加了主从备份功能,提高集群的数据可用性。
镜像集群虽然支持主从,但主从同步并不是强一致的,某些情况下可能有数据丢失的风险。因此在 RabbitMQ 的 3.8 版本以后,推出了新的功能:仲裁队列来代替镜像集群,底层采用Raft 协议确保主从的数据一致性。
二、普通集群
普通集群,或者叫标准集群(classic cluster),具备下列特征:
(1)会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。
(2)当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回 (3)队列所在节点宕机,队列中的消息就会丢失
1. 集群部署
我们先来看普通模式集群,我们的计划部署3节点的mq集群:
集群中的节点标示默认都是:`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)主宕机后,镜像节点会替代成新的主
镜像模式的配置有3种模式:
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类型。
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: /