【rabbitmq】RabbitMQ 集群与网络分区

网络分区(network partitions)

官网-网络分区html

网络设备故障致使的网络分裂。好比,存在A\B\C\D\E五个节点,A\B处于同一子网,B\C\D处于另一子网,中间经过交换机相连。若两个子网间的交换机故障了即发生了网络分区,A\B和C\D\E便不能通信。
某些系统是partition-tolerant的,也即,即便发生了网络分区系统分裂为了多个子系统,整个系统仍能正常工做。node

RabbitMQ cluster不能很好地处理Network Partition。RabbitMQ将queue、exchange、bindings等信息存储在Erlang的分布式数据库Mnesia中。因此出现Network partition时RabbitMQ的众多行为与Mnesia的行为密切相关。数据库

Network Partition的断定

若某一node在一段时间内(取决于net_ticktime的设置)不能与另外一node取得联系,则Mnesia认为未能与之取得联系的node宕掉了。若两个node彼此恢复联系了,但都曾觉得对方宕掉了,则Manesia判定发生过Network partition。数组

发生Network Partition后RabbitMQ的行为

若发生了network partition,cluster中的双方(或多方)将独立存在,每一方都将认为其余方已经崩溃了。Queues、bindings、exchanges能够各自独立的建立、删除。对于Mirrored queues,处于不一样network partition的每一方都会拥有各自的master,且各自独立的读写。(也可能发生其余诡异的行为)。若network partition恢复了,cluster的状态并不能自动恢复到network partition发生前的状态,直至采起措施进行修复。安全

网络分区的可能缘由

只要cluster中的不一样node自身没有失效但之间的通讯发生了中断均可认为是发生了Partitions。好比,整个OS的挂起会致使其中的cluster nodes的挂起,但这些nodes却不认为自身失效或中止了,而cluster中的其它nodes不能与之取得联系,会认为这些nodes down掉了。举个例子:若cluster中的一个node运行在笔记本电脑上,合上电脑屏幕就有可能致使node挂起。另外,若cluster中的node运行在虚拟机中,则管理程序可能致使虚拟机挂起,从而使node挂起。网络

  • 状况1:集群中的nodes,都没有故障下线,可是node之间通讯中断;
  • 状况2:暂停/恢复运行中node的操做系统也可能致使network分区:暂停的node不认为它已经fail或stop,但集群中的其余nodes认为它已经fail了。
  • 状况3:发生这种状况的最多见缘由是:虚拟机已被虚拟机管理程序挂起;
  • 状况4:虚拟机的迁移(rabbitmq运行在该vm上),也可能会致使vm被挂起,从而发生网络分区
  • 状况总结:就是某个node因各类缘由,和集群中的其余节点发生通讯中断,虽然该节点不认为本身下线,可是集群中的其余节点已经认为该节点下线了。

检查网络分区

能够经过rabbitmqctl cluster_status来查看是否发生了网络分区
正常的状态信息:分布式

[root@rmq-node3 ~]# rabbitmqctl cluster_status
Cluster status of node 'rabbit@rmq-node3'
[{nodes,[{disc,['rabbit@rmq-node2','rabbit@rmq-node1']},
         {ram,['rabbit@rmq-node3']}]},
 {running_nodes,['rabbit@rmq-node1','rabbit@rmq-node2','rabbit@rmq-node3']},
 {cluster_name,<<"rabbit@rmq-node1">>},
 {partitions,[]},                    #注意,这里为空数组,代表没有发生网络分区
 {alarms,[{'rabbit@rmq-node1',[]},
          {'rabbit@rmq-node2',[]},
          {'rabbit@rmq-node3',[]}]}]

发生网络分区的状态信息:this

[root@rmq-node3 ~]# rabbitmqctl cluster_status
Cluster status of node 'rabbit@rmq-node3'
[{nodes,[{disc,['rabbit@rmq-node2','rabbit@rmq-node1']},
         {ram,['rabbit@rmq-node3']}]},
 {running_nodes,['rabbit@rmq-node1','rabbit@rmq-node2','rabbit@rmq-node3']},
 {cluster_name,<<"rabbit@rmq-node1">>},
 {partitions,[{'rabbit@rmq-node1',['rabbit@rmq-node2','rabbit@rmq-node3']}]},  #这里是发生了network partitions
 {alarms,[{'rabbit@rmq-node1',[]},
          {'rabbit@rmq-node2',[]},
          {'rabbit@rmq-node3',[]}]}]

当发生网络分区时,会提示以下信息:操作系统

While running in this partitioned state, changes (such as queue or exchange declaration and binding) which take place in one partition will not be visible to other partition(s). Other behaviour is not guaranteed.  
==>代表 元数据的改变,不会在节点之间同步

也能够经过查看日志找到该问题:日志

vi /var/log/rabbitmq/rabbit-xxx.log

=ERROR REPORT==== 9-Aug-2018::20:15:45 ===
Mnesia('rabbit@rmq-node2'): ** ERROR ** mnesia_event got {inconsistent_database, starting_partitioned_network, 'rabbit@rmq-node1'}

网络分区的恢复

首先选一个最信任的partition,Mnesia使用该partition中的状态,其余partitions中发生的变化都将丢失。
中止其余partitions中的全部nodes,以后重启这些nodes。当这些nodes从新加入cluster后将从信任的partition恢复状态。
最后还需重启信任的partition中的全部nodes以清除network partition的警告信息

Rabbitmq自动处理网络分区的3种模式

RabbitMQ提供了3种自动处理network partitions的方式:默认为ignore模式,也即须要手工处理

  1. pause-minority mode:暂停少数模式;
  2. pause-if-all-down mode:暂停-若是所有中止模式
  3. autoheal mode:自动愈合模式

pause-minority mode:暂停少数模式

在pause-minority模式下,察觉其余nodes down掉后,RabbitMQ将自动暂停认为本身是少数派的 nodes(例如小于或等于总nodes数的一半),network partition一旦发生,“少数派”的nodes将马上暂停,直至partition结束后从新恢复。这能够保证在network partition发生时,至多只有一个partition中的nodes继续运行。(牺牲可用性保证一致性)
若全部分区的nodes个数都小于总nodes个数一半,则意味着全部分区的nodes都会认为本身是少数派,即全部nodes都将暂停;

pause-if-all-down mode:暂停-若是所有中止模式

http://www.rabbitmq.com/partitions.html

autoheal模式

在autoheal模式下一旦发生了partition,RabbitMQ将自动肯定一个优胜partition,而后重启全部不在优胜partition中的nodes。
获胜的partition为拥有最多客户端链接的partition(若链接相同则为节点最多的partition)。
关于自动处理partitions的设置在配置文件的cluster_partition_handling参数中进行。

各自的适用场景

network partitions自动处理并不能保证cluster不出任何问题。
通常来讲可做以下选择:

  • ignore:若网络很是可靠。全部nodes在同一机架,经过交换机链接,该交换机也是通往外部网络的出口。在cluster的某一部分故障时不但愿其他部分受影响。或者cluster只有两个node。
  • pause_minority:网络较不可靠。cluster处于EC2的3个AZ中,假定每次至多只有其中一个AZ故障,想要剩余的AZ继续提供服务而故障的AZ中的nodes在AZ恢复后从新自动加入到cluster。
  • autoheal:网络很不可靠。与数据完整性相比更关注服务的持续性。cluster只有两个node。

关于pause-minority模式

暂停的nodes上Erlang VM将继续运行但不监放任何端口或者作其余工做。它们将每秒检测一次cluster中的其余nodes是否可见,若可见则从pause状态唤醒。 注意: nodes在启动时不会进入paused状态,即便是处于“少数派”; RabbitMQ可能会暂停非严格意义上的“少数派”中的nodes。如,包含多于总nodes总数一半的nodes。所以在只包含两个nodes的cluster中使用pause-minority模式并不是好主意,由于在network partition发生或者node失败时有可能两个node都会暂停。然而,在包含两个以上nodes的cluster中pause_minority模式要比ignore更安全; 对于因cluster nodes 挂起引发的partitions pause_minority模式无能为力。由于挂起的node将不能看到剩余node是否恢复“可见”,于是不能触发从cluster中断开。

相关文章
相关标签/搜索