前面章节我们介绍了如何安装及运行 RabbitMQ 服务,不过这些是单机版的 RabbitMQ 服务。单机版的 RabbitMQ 服务用来学习完全没有问题,但是无法满足应用程序复杂的生产环境真实的要求。
如果 RabbitMQ 服务器遇到内存崩溃、机器掉电或者主板故障等情况,该怎么办?
如果单台 RabbitMQ 服务器可以满足每秒 1000 条消息的吞吐量,如果应用需要 RabbitMQ 服务满足每秒 10 万条消息的吞吐量呢?
最简单办法就是购买昂贵的服务器来增强单机 RabbitMQ 服务的性能,毕竟单机性能是有限的,应用程序性能需求是无限的。因此,搭建一个 RabbitMQ 集群才是解决实际问题的关键点。
RabbitMQ 集群允许消费者和生产者在 RabbitMQ 单个节点崩惯的情况下继续运行,它可以通过添加更多的节点来线性地扩展消息通信的吞吐量。当失去一个 RabbitMQ 节点时,客户端能够重新连接到集群中的任何其他节点并继续生产或者消费。
在 RabbitMQ 单机版服务中,存在消息丢失的情况。为此,我们搭建了 RabbitMQ 集群,那么 RabbitMQ 集群就能够保证消息不丢失吗?
不能保证,即使是 RabbitMQ 集群,也有可能丢失消息。当集群中一个 RabbitMQ 节点崩溃时,该节点中的所有队列中的消息也会丢失。RabbitMQ 集群中的所有节点都会备份所有的元数据,元数据包含如下:
队列元数据:包含队列名称及属性
交换器元数据:包含交换器名称及属性
绑定关系元数据:包含交换器与队列、交换器和交换器之间的绑定关系
vhost 虚拟机元数据:包含虚拟机内部的队列、交换器和绑定提供命名空间及安全属性
RabbitMQ 基于存储空间和性能的考虑。在集群中创建队列时,只会在单个节点而不是在所有节点上创建队列的进程,并只队列的宿主节点包含完整的队列信息,如:队列元数据、队列的状态、队列中的消息。
其他非宿主节点只知道队列的元数据和指向该队列宿主节点的指针。因此当集群节点崩溃时,该节点的队列进程和关联的绑定都会消失。附加在那些队列上的消费者也会丢失其所订阅的信息,井且任何匹配该队列绑定信息的新消息也都会消失。
不同于队列那样拥有自己的进程,交换器其实只是一个名称和绑定列表。当消息发布到交换器时,实际上是由所连接的信道(Channel)将消息上的路由键同交换器的绑定列表进行比较,然后再路由消息。
当创建一个新的交换器时,RabbitMQ 所要做的就是将绑定列表添加到集群中的所有节点上。
这样,每个节点上的每条信道都可以访问到新的交换器了。