RabbitMQ集群
1.普通集群模式
在普通集群模式下,交换器Exchange的元数据信息在所有节点上是一致的,而队列Queue的完整数据则只会存在于它所创建的那个节点上。其他节点只知道这个队列的元数据信息和一个指向队列的指针。
1.1 元数据同步
会同步四种类型的内部元数据:
- 队列元数据:队列名称和它的属性;
- 交换器元数据:交换器名称,类型,属性;
- 绑定元数据:如何将消息路由到队列的数据;
- vhost元数据:为vhost内部的队列,交换器,绑定提供命名空间和安全属性。
因此当用户访问其中任何一个RabbitMQ节点时,通过rabbitmqctl
查询到的queue/user/exchange/vhost等信息都是相同的。
1.2 集群中发布/订阅消息的基本流程
- 当客户端连接到队列所在的节点:有一个消息生产者或消息消费者进行消息的发布或订阅,此时的集群中的消息收发只与节点1相关,直接发布或订阅即可;
- 当客户端连接的节点没有队列数据:此时队列1的完整数据不在队列2和3上,那么着两个节点主要起路由转发的作用,根据这两个节点上的节点1元数据转发到节点1上,最终发送的消息还是会存储到节点1的队列1上。
1.3 集群节点的类型
-
磁盘节点
将配置信息和元数据存储在磁盘上,单节点系统必须是磁盘节点,否则每次重启RabbitMQ之后所有的系统配置信息都会丢失。
-
内存节点
将配置信息和元数据存在内存中,性能优于磁盘节点。
RabbitMQ要求集群中至少有一个磁盘节点,当节点加入和离开集群时,必须通知磁盘节点,如果集群中唯一的磁盘节点崩溃了,集群是可以运行的,但不能更改任何东西,因此一般在集群中设置两个磁盘节点,只要一个可以,就能正常操作。
1.4 总结
普通集群模式不会保证队列的高可用性。尽管交换器,绑定这些可以复制到集群中的任何一个节点,但是队列内容不会复制,当队列节点宕机时直接导致该队列无法应用,只能等待重启。
要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群中的每个节点,必须创建镜像队列。
2.镜像队列集群模式
镜像队列是基于普通的集群模式的,再配置一些policy(策略)就可以实现镜像队列。
2.1 镜像队列的Policy
可以在RabbitMQ的管理页面中设置,Admin—>Policy下开始创建Policy:
-
Name:Policy的名称;
-
Pattern:匹配模式;
-
Priority:优先级;
-
Definition:一些模式的定义,
-
ha-mode:指定镜像队列的模式,有效值为all/exactly/nodes;
-
all:在集群中所有的节点上进行镜像;
- exactly:在指定个数的节点上进行镜像,节点个数由ha-params指定;
- nodes:在指定的节点上进行镜像,节点名称通过ha-params指定。
-
-
ha-sync-mode:指定镜像队列中消息的同步方式,有效值为manually/automatic;
-
manually:默认,手动同步;
-
automatic:自动同步,一定要设置为自动同步,否则消息在镜像队列中是不会自动同步的,和普通集群模式一样,新节点加入时不会自动同步消息和元数据,只能通过命令手动去同步。
-
-
2.2 服务提供的方式
镜像队列中queue有master节点和slave节点,这里的master和slave是针对一个queue而言的,而部署一个node作为所有queue的master。
一个queue第一次创建的node为它的master节点,其他为slave节点。
镜像队列集群模式中,对某个queue,只有master对外提供服务,其他slave只提供备份服务,在master所在节点不可用时,选出一个slave作为新的master继续对外提供服务。
- 当客户端请求到master节点,直接将消息返回,同时master节点通过GM(Guranteed Multicast,可靠广播)协议将queue的最新状态广播到slave节点。GM协议可以保证广播消息的原子性,要么都更新,要么都不更新。
- 当客户端请求到slave节点,slave节点需要将请求重定向到master节点,master节点再将消息返回,同时通过GM协议广播queue的最新状态。
2.3 新增节点
如果有新增节点,RabbitMQ不会同步之前的历史数据,新节点只会复制该节点加入到集群之后新增的消息。
RabbitMQ集群内会维护节点的状态是否已经同步,当master节点宕机时选一个slave作为master,集群会选一个最老的节点作为新的master,最老的节点肯定是保证最多的状态已同步。
节点重启也按照新几点来处理。
2.4 节点失效
如果某个slave失效,不用做任何操作;
如果master失效,从slave中选最老的一个作为新的master,因为最老的slave与之前的master之间的同步状态是做好的。
如果存在没有任何一个slave与master完全同步的情况,那么前任master中未被同步的消息会丢失。
2.5 消息同步
将新节点加入已存在的镜像队列时,默认ha-sync-mode=manual
,镜像队列中的消息不会主动同步到新节点,除非显示调用同步命令。
当设为ha-sync-mode=automatic
时,新加入节点时会默认同步已知的镜像队列。同步过程中,队列会阻塞,无法对其进行操作,直到同步完毕。
2.6 总结
镜像节点在集群中的其他节点拥有从队列拷贝,一旦master节点不可用,最老的slave队列会被选举未新的master。但是镜像队列不能作为负载均衡使用,因为每个操作在所有系欸但都要做一遍,会降低系统性能。