RabbitMQ集群是按照低延迟环境设计的,千万不要跨越WAN或者互联网来搭建RabbitMQ集群。若是必定要在高延迟环境下使用RabbitMQ集群,能够参考使用Shovel和Federation工具。安全
RabbitMQ社区中的传统观念要求集群中节点数量的上限在32至64个,由于每向集群添加一个节点,就添加了同步的复杂性。集群中的每一个节点必须知道其余节点的信息,这种非线性的复杂度会拖慢消息投递和集群管理。bash
RabbitMQ集群设计目的有两个:网络
当一个RabbitMQ集群节点崩溃时,该节点上队列的消息也会消失。这事由于RabbitMQ默认不会将队列的内容复制到整个集群上。若是不进行特别的配置,这些消息仅存在于队列所属的那个节点上。架构
RabbitMQ会始终记录如下四种类型的内部元数据:工具
当你引入集群时,RabbitMQ须要追踪新的元数据类型 —— 集群节点位置,以及节点与已记录的其余类型元数据的关系。集群也提供了将元数据存储到磁盘或内存中的选项。性能
不是每个节点都有全部队列的彻底拷贝。 在集群中建立队列的话,集群只会在单个节点(而不是全部节点)上建立完整的队列信息。 结果是,只有队列的全部者节点,知道有关队列的全部信息。 其余非队列全部者的节点们,只知道队列的元数据和指向队列存在的那个节点的指针。 所以,当集群节点崩溃时,该节点的队列和关联的绑定就都消失了。 附加在那些队列上的消费者丢失了订阅。 而且任何匹配该队列绑定信息的新消息也丢失了。
若是消费者要消费的队列的所在节点故障了,而该队列是持久化的,那么想要继续消费,惟一的办法就是恢复故障节点。当失败节点恢复后加入集群,该节点上的队列消息不会丢失。spa
尝试在持久化队列节点故障后,从新声明队列,会获得一个404 NOT_FOUND错误。但若是队列不是持久化的,那么从新声明就会成功。插件
RabbitMQ设计上不将队列内容和状态复制到全部的节点上,主要有两个缘由:设计
存储空间 —— 若是一个节点能够存储1GB的消息,那么在多个节点之间复制消息则会浪费多个G的空间;指针
性能因素 —— 消息的发布须要将消息复制到每个节点,对于持久化消息来讲,每次都会触发磁盘活动,每次新增节点,网络和磁盘负载都会增长;
另外,在向队列发送消息时,只有队列的全部节点,才会收到磁盘操做的影响。其余非全部节点,只须要将接收到的消息传递给全部者节点便可。
所以,往Rabbit集群中添加更多的节点,就意味着将拥有更多的节点来传播消息,多个节点会带来性能的提高。
交换器,本质上就是一个名称和队列绑定的列表。
当你将消息发布到交换器时,其实是由链接的信道,根据消息上的路由键,去交换器绑定列表中进行比较,而后路由消息到队列中。
因为交换器只不过是一张表,所以将这张表在集群中复制很简单,当建立一个新的交换器时,RabbitMQ所要作的是将交换器添加到集群中的全部节点上。
集群的消息可靠性与单点模式基本一致。AMQP的Basic.Publish命令不会返回消息的状态。这意味着当信道节点崩溃时,信道可能仍然在路由消息,解决方案是使用事务,或发布确认模式。
RabbitMQ的集群大体上可分为3类:
当建立集群时,至少保证一个磁盘节点和若干个内存节点。不管哪一种节点,都不会影响消息持久化。
当有多个磁盘节点时,就能在发生硬件故障时更加游刃有余。
若存在多个磁盘节点,在发生故障恢复时可能会出现状态不一致的状况,这种时候,可关闭集群并按照顺序从新启动节点。
统计节点,只能和磁盘节点搭配使用。它负责收集集群中每一个节点的所有统计数据和状态数据。在任什么时候候,一个集群只能有一个统计节点。
在拥有两个磁盘节点的集群中,若是主节点发生故障,统计节点将指派给备用的磁盘节点。
若是只有一个磁盘节点,当这个节点发生故障后,集群仍是能够继续路由消息,可是不能作如下操做:
最好是设置一个以上的磁盘节点,在某个磁盘节点故障时,还有备用的磁盘节点可用。
当内存节点添加到集群或从新加入到集群时,他们会链接到预先配置的磁盘节点,下载集群元数据。当添加内存节点时,确保告知该内存节点全部的磁盘节点。
集群的升级是半自动化的,在没有准备的状况下解压新版本的RabbitMQ覆盖旧版本,会抹去集群上全部配置和数据。若是要保留这些,须要进行一些操做。
首先,经过Management插件备份配置;
而后,关闭全部生产者并等待全部消费者消费完队列中全部的消息(使用rabbitmqctl观察队列状态);
接着,关闭节点并解压新版本的RabbitMQ;
随后,选择其中一个磁盘节点做为升级节点,当它启动时,该节点会将持久化的集群数据升级到新版本,而后在启动其余的磁盘节点;
最后,启动内存节点,这样就会让集群中运行新版本的RabbitMQ了,并且元数据都会保留;
在RabbitMQ2.6版本后,RabbitMQ团队给集群带来了内建的双冗余选项:镜像队列。
想普通队列那样,镜像队列的主拷贝仅存在于一个节点(主队列,Master)上,但与普通队列不一样的是,镜像节点在集群中的其余节点上拥有从队列(slave)拷贝。一旦队列主节点不可用,最老的从队列将被选举为主队列。
在定义队列时,加入参数:
x-ha-policy = all
这意味着队列被镜像到集群中的全部节点上。若是在该队列声明以后,集群又新增了节点,那么该节点也会自动托管一份队列的从拷贝。
消息发送到队列时,若是队列是镜像队列,那么也要将消息投递到镜像队列的从拷贝。
想确保消息没有丢失的话,同样可使用发布确认模式,不一样的是,RabbitMQ会在全部队列安全的接收了消息后在通知你。
这里须要有从发布者和消费者两方面说一下异常状况:
注意:若是消费者链接在从拷贝,当主拷贝发生变化时,RabbitMQ会发送给客户端一个Consumer Cancellation的通知,告知客户端发生了变化。若是你的客户端不支持这个通知处理的话,你的程序会空跑,觉得队列中没有消息能够消费了。 若是你的客户端不支持这个消费者取消通知处理,那么应该避免使用镜像队列!!!