RabbitMQ面试主题:高可用性

RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式

单机模式不存在高可用。
普通集群模式也不存在高可用性,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。但是你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上 拉取数据过来。这种方式确实很麻烦,也不怎么好,没做到所谓的分布式,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个 queue 所在实 例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。而且如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让 RabbitMQ 落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个 queue 拉取数据。
镜像集群模式的策略是高可用策略,指定的时候可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的 节点上去了。

镜像集群脑裂问题

网络分区中一个节点在一分钟(或者一个net_ticktime时间)内不能连接上另一个节点,那么Mnesia会认为另一个节点已经挂了。就算之后两个节点连通,但是这两个节点都认为对方已经挂了,Mnesia此时认定发生了网络分区的情况。rabbitmq出错日志如下:

例如:Mnesia(‘rabbit@lg-mq02’): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, ‘rabbit@lg-mq01’}

解决办法

原因是rabbitmq集群在配置时未设置出现网络分区处理策略,先要将集群恢复正常,再设置出现网络分区处理策略,步骤如下:
(1)首先需要挑选一个信任的分区,这个分区才有决定Mnesia内容的权限,发生在其他分区的改变将不被记录到Mnesia中而直接丢弃。
(2)停止(stop)其他分区的节点,然后启动(start)这些节点,之后重新将这些节点加入到当前信任的分区之中。

rabbitmqctl stop_app
rabbitmqctl start_app
(3)最后,你应该重启(restart)信任的分区中所有的节点,以去除告警。
你也可以简单的关闭整个集群的节点,然后再启动每一个节点,当然,你要确保你启动的第一个节点在你所信任的分区之中。
(4)设置出现网络分区处理策略,这里设置为autoheal,下面会详细说明其它策略
在/etc/rabbitmq下新建rabbitmq.conf,加入:

[
{rabbit,
[{tcp_listeners,[5672]},
{cluster_partition_handling, autoheal}
]}
].

网络分区处理策略

有以下3种处理策略:
(1)ignore
默认类型,不处理。
要求你所在的网络环境非常可靠。例如,你的所有 node 都在同一个机架上,通过交换机互联,并且该交换机还是与外界通信的必经之路。
(2)pause_minority
rabbitmq节点感知集群中其他节点down掉时,会判断自己在集群中处于多数派还是少数派,也就是判断与自己形成集群的节点个数在整个集群中的比例是否超过一半。如果是多数派,则正常工作,如果是少数派,则会停止rabbit应用并不断检测直到自己成为多数派的一员后再次启动rabbit应用。注意:这种处理方式集群通常由奇数个节点组成。在CAP中,优先保证了CP。
注意:pause_minority适用情形有限制,如3个节点集群,每次只down1个时,此模式适用。但如果网络都出问题,3节点会独立形成3个集群。
(3)autoheal
你的网络环境可能是不可靠的。你会更加关心服务的可持续性,而非数据完整性。你可以构建一个包含2个node的集群。
当网络分区恢复后,rabbitmq各分区彼此进行协商,分区中客户端连接数最多的为胜者,其余的全部会进行重启,恢复到同步状态。

You May Also Like

About the Author: daidai5771

发表评论

电子邮件地址不会被公开。 必填项已用*标注