RabbitMQ镜像队列

Stella981
• 阅读 662

本节主要讲述镜像队列。镜像队列的主要作用是用来解决队列的单点故障。

镜像队列主要有两种类型:master和slave。master和slave节点位于同一个集群中。master只要一个节点,slave可以有多个节点。

生产者发送到主节点消息会同时被发往各个slave节点,除了发送消息,其他动作只会发给master,然后通过master广播给其他slave。

master挂掉以后,根据slave加入的时间顺序排列,时间长的提升为master。

镜像队列的backing_queue不再使用rabbit_variable_queue。master节点的queue使用rabbit_mirror_queue_master,它内部包裹了普通backing_queue进行本地消息消息持久化处理,在此基础上增加了将消息和ack复制到所有镜像的功能,slave节点的queue使用rabbit_mirror_queue_slave。

RabbitMQ镜像队列

rabbit_mirror_queue_master的操作都会通过组播GM的方式同步到各个slave中。GM负责消息的广播,rabbitmirrorqueueslave负责回调处理,而master上的回调处理是由coordinator负责完成的。如前所述,除了Basic.Publish,所有的操作都是通过master来完成的,master对消息进行处理的同时将消息的处理通过GM广播给所有的slave,slave的GM收到消息后,通过回调交由rabbit_mirror_queue_slave进行实际的处理。

GM模块实现的是一种可靠的组播通信协议,该协议能够保证组播消息的原子性,即保证组中活着的节点要么都收到消息要么都收不到,它的实现大致为:将所有的节点形成一个循环链表,每个节点都会监控位于自己左右两边的节点,当有节点新增时,相邻的节点保证当前广播的消息会复制到新的节点上;当有节点失效时,相邻的节点会接管以保证本次广播的消息会复制到所有的节点。

在master和slave上的这些GM形成一个组(gm_group),这个组的信息会记录在Mnesia中。不同的镜像队列形成不同的组。操作命令从master对应的GM发出后,顺着链表传送到所有的节点。由于所有节点组成了一个循环链表, master对应的GM最终会收到自己发送的操作命令,这个时候master就知道该操作命令都同步到了所有的slave上。

当master挂掉之后,会有以下连锁反应:

  1. 与master连接的客户端连接全部断开。

  2. 选举最老的slave作为新的master,因为最老的slave与旧的master之间的同步状态应该是最好的。如果此时所有slave处于未同步状态,则未同步的消息会丢失。

  3. 新的master重新入队所有unack的消息,因为新的slave无法区分这些unack的消息是否己经到达客户端,或者是ack信息丢失在老的master链路上,再或者是丢失在老的master 组播ack消息到所有slave的链路上,所以出于消息可靠性的考虑,重新入队所有unack的消息,不过此时客户端可能会有重复消息。

  4. 如果客户端连接着slave,并且Basic.Consume消费时指定了x-cancel-on-ha­failover参数,那么断开之时客户端会收到一个Consumer Cancellation Notification的通知,消费者客户端中会回调Consumer接口的handleCancel方法。如果未指定x-cancel­on-ha-failover参数,那么消费者将无法感知master宕机。

  5. rabbitmqctl set_policy [-p vhost] [--priority priority] [--apply-to apply-to] {name} {pattern} {definition}

definition中需要包含3个部分:

  • ha-mode:指明镜像队列的模式,有效值为all、exactly、nodes,默认为all。all表示在集群中所有的节点上进行镜像;exactly表示在指定个数的节点上进行镜像,节点个数由ha-params指定;nodes表示在指定节点上进行镜像,节点名称过ha-params指定,节点的名称通常类似于rabbit@hostname。

  • ha-params:不同的ha-mode配置中需要用到的参数。

  • ha-sync-mode:队列中消息的同步方式,有效值为automatic和manual。

  • ha-promote-on-shutdown:加后面的讲述

将新节点加入己存在的镜像队列时,默认情况下ha-sync-mode取值为manual。镜像队列中的消息不会主动同步到新的slave中,除非显式调用同步命令。当调用同步命令后,队列开始阻塞,无法对其进行其他操作,直到同步完成。当ha-sync-mode设置为automatic时, 新加入的slave会默认同步己知的镜像队列

当所有slave都出现未同步状态,并且ha-promote-on-shutdown设置为when-synced(默认)时,如果master因为主动原因停掉,比如通过rabbitmqctl stop命令或者优雅关闭操作系统,那么slave不会接管master,也就是此时镜像队列不可用;但是如果master因为被动原因停掉,比如Erlang虚拟机或者操作系统崩溃,那么slave会接管master。这个配置项隐含的价值取向是保证消息可靠不丢失,同时放弃了可用性。如果ha-promote-on-shutdown设置为always,那么不论master因为何种原因停止,slave都会接管master,优先保证可用性,不过消息可能会丢失。

  1. # 命令可以查看哪些slaves已经完成同步

  2. rabbitmqctl list_queues name slave_pids synchronised_slave_pids

  3. # 手动同步队列

  4. rabbitmqctl sync_queue {name}

  5. # 取消队列的同步操作

  6. rabbitmqctl cancel_sync_queue {name}

本文分享自微信公众号 - shysh95(shysh95)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
STM32 SPI详解
1、SPI简介SPI规定了两个SPI设备之间通信必须由主设备(Master)来控制次设备(Slave).一个Master设备可以通过提供Clock以及对Slave设备进行片选(SlaveSelect)来控制多个Slave设备,SPI协议还规定Slave设备的Clock由Master设备通
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Redis缓存高可用集群
在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般。
Wesley13 Wesley13
3年前
ubuntu 安装 redis集群
计划部署三个虚拟机三个master节点三个slave节点:IP:192.168.26.133 port:7133(master)  port:8133(slave)IP:192.168.26.134  port:7134(master)  port:8134(slave)IP:192.168.26.135port:7135(mas
Stella981 Stella981
3年前
Centos7.6部署redis6.0.8集群(redis cluster模式)
集群规划:三台服务器各部署一个主节点、一个从节点,同一台服务器上不是直接主从关系。服务器角色ip:端口node1master1/slave2192.168.146.199:6379/192.168.146.199:6380node2master2/slave3192.168.146.200:6379/192.168.1
Stella981 Stella981
3年前
Redis学习
主从复制官方文档:https://redis.io/topics/replicationRedis中的主从复制,也就是MasterSlave模型,有以下特点  Master可以拥有多个slave  多个slave不仅可以连接同一个master,还可以连接到其他的slave  主从复制不会阻塞master,在同步数据时,maste
Wesley13 Wesley13
3年前
mysql主从复制原理及实现
一.主从复制原理利用MySQL提供的Replication,其实就是Slave从Master获取Binarylog文件,然后再本地镜像的执行日志中记录的操作。由于主从复制的过程是异步的,因此Slave和Master之间的数据有可能存在延迟的现象,此时只能保证数据最终的一致性。在master与slave之间实现整个复制过程主要由三个线程来完成
Stella981 Stella981
3年前
FastCFS binlog机制简介
  FastCFS采用经典的Master/Slave结构及数据同步复制的做法。如果slave在线,master同步调用slave;否则slave将进入数据恢复阶段,追上master的最新进度后,slave切换为在线状态,此后master将数据同步复制到slave。  FastCFS采用binlog记录数据更改操作,binlog中不会记录变
Wesley13 Wesley13
3年前
mysql的复制详解
复制线程  复制线程主要包括三个线程:master转储线程:在master出现数据更新时,会生成一个转储线程将二进制日志中的语句发送到slaveslaveI/O线程:在master生成转储线程的同时,slave同时会生成一个I/O线程将从master读取的语句,写入中继日志。slave的SQL线程:sl