RabbitMQ(五)镜像队列

一、镜像队列
rabbitmq的集群创建后,默认消息只存在于队列所在节点,当此节点故障后,消息就丢失了。
为了解决上述消息丢失的问题,引入RabbitMQ的镜像队列机制,将queue镜像到cluster中其他的节点之上。
在该实现下,如果集群中的一个节点失效了,queue能自动地切换到镜像中的另一个节点以保证服务的可用性。
镜像队列有如下特性:
  • 每一个镜像队列都包含一个master和1个或多个slave
  • 如果master失效了,最老的slave被选中为master
  • 镜像队列不是负载均衡,镜像队列无法提升消息的传输效率
  • 对exclusive队列设置镜像并不会有任何作用,因为exclusive队列是连接独占的,当连接断开,队列自动删除
 
二、配置镜像队列
镜像队列是在普通集群搭建后,通过设置同步策略来实现的

rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
-p Vhost: 可选参数,针对指定vhost下的queue进行设置
Name: policy的名称
Pattern: queue的匹配模式(正则表达式)
Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode
        ha-mode:指明镜像队列的模式,有效值为 all/exactly/nodes
            all:表示在集群中所有的节点上进行镜像
            exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定
            nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定
        ha-params:作为参数,为ha-mode的补充
        ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual
priority:可选参数,policy的优先级

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' --apply-to all
三、镜像队列的结构

1、镜像队列基本上就是一个特殊的BackingQueue,它内部包裹了一个普通的BackingQueue做本地消息持久化处理,在此基础上增加了将消息和ack复制到所有镜像的功能。
2、所有对mirror_queue_master的操作,会通过组播的方式同步到各slave节点。
3、GM负责消息的组播,mirror_queue_slave负责回调处理,而master上的回调处理是由coordinator负责完成。
4、mirror_queue_slave中包含了普通的BackingQueue进行消息的存储,master节点中BackingQueue包含在mirror_queue_master中由AMQQueue进行调用。

四、组播模块GM
GM, Guarenteed Multicast. GM模块实现的一种可靠的组播通讯协议,该协议能够保证组播消息的原子性,即保证组中活着的节点要么都收到消息要么都收不到。
在master节点和slave节点上的gm形成一个组,不同的镜像队列形成不同的group。
它的实现大致如下:
将所有的节点形成一个循环链表,每个节点都会监控位于自己左右两边的节点
1、当有节点新增时,相邻的节点保证当前广播的消息会复制到新的节点上
2、当有节点失效时,相邻的节点会接管保证本次广播的消息会复制到所有的节点
 
五、新增节点的消息同步
一个queue正在同步,所有对于其他的queues的操作将会被阻塞,不建议在生产的active队列(有生产消费消息)中操作。
 
一个节点可以在任何时候加入集群之中。
根据queue的配置,当新节点加入进来的时候,这个queue有可能在这个新的节点上添加一个镜像,此时这个镜像是空的。
什么时候进行消息同步呢?这个涉及到ha-sync-mode这个的参数。
1、ha-sync-mode=automatic,新加入节点时会默认同步已知的镜像队列
2、ha-sync-mode=manual(默认值)
镜像队列中的消息不会主动同步到新节点,除非显式调用同步命令。当调用同步命令后,队列开始阻塞,无法对其进行操作,直到同步完毕

rabbitmqctl list_queues name slave_pids synchronised_slave_pids 查看队列同步情况
rabbitmqctl sync_queue name    同步指定队列
rabbitmqctl cancel_sync_queue name 取消同步
在此状态下,可选择另外一种方式,避免影响。新加入的镜像可以收到生产者新发送过来的消息,其内容与其他镜像的尾部保持一致。随着queue中的消息被逐渐的消费,新加入的镜像中“错失”的消息逐渐减少,直到与其他镜像保持一致。
 
六、队列或节点故障
1、master和全部或部分slave处于同步状态
一般情况最老的slave被选中为master
 
2、所有slave都处于未同步状态
1)ha-promote-on-shutdown=when-synced(默认)
master因为主动的原因停掉,比如是通过rabbitmqctl stop命令停止或者优雅关闭OS,那么slave不会接管master,也就是此时镜像队列不可用
master因为被动原因停掉,比如VM或者OS crash了,那么slave会接管master
 
2)ha-promote-on-shutdown=always
不论master因为何种原因停止,slave都会接管master,优先保证可用性。

原文地址:https://www.cnblogs.com/guoxianqi2020/p/13998500.html