一、集群与网络分区
RabbitMQ集群不能很好滴容忍网络分区。如果你正在考虑跨越广域网部署集群,则你最好使用或者。
然而事故发生是不可避免,本文描述如何检测网络分区、在分区产生时会产生哪些不良影响,怎样从网络分区中恢复。
RabbitMQ存储信息到Erlang的分布式数据库Mnesia中,包括queue、exchange、binding等。围绕网络分区的许多详细故障信息都与Mnesia的行为有关。
二、检测网络分区
如果一分钟左右(net_ticktime参看)另一个节点不能与该节点取得联系,则Mnesia通常会判定该节点down了。如果两个节点能够联系得上了,但又都认为对方down了,则Mnesia将判定分区发生了。这个现象将会以如下形式写入到RabbitMQ的日志中:
=ERROR REPORT==== X15-Oct-2012::18:02:30 ===
Mnesia(rabbit@smacmullen): ** ERROR ** mnesia_event got
{inconsistent_database, running_partitioned_network, hare@smacmullen}
当节点启动后,RabbitMQ节点将会记录这种事件是否发生过,并且通过rabbitmqctl cluster_status和管理插件来显示这个信息。
rabbitmqctl cluster_status正常状态会显示空分区列表:
#rabbitmqctl cluster_status
Cluster status node rabbit@smacullen ...
[{nodes, [{disc, [hare@smacmullen, rabbit@smacmullen]}]},
{running_nodes, [rabbit@smacmullen, hare@smacmullen]},
{partitions, []}]
... done.
然而,如果一个网络分区已经发生了,则分区节点信息会显示在列表中:
#rabbitmqctl cluster_status
Cluster status node rabbit@smacullen ...
[{nodes, [{disc, [hare@smacmullen, rabbit@smacmullen]}]},
{running_nodes, [rabbit@smacmullen, hare@smacmullen]},
{partitions, [{rabbit@smacmullen, [hare@smacmullen]},
{hare@smacmullen, [rabbit@smacmullen]}]}]
... done.
管理插件API将会通过/api/nodes为每个分区节点返回分区信息,管理插件UI将会在overview页面显示一个巨大的红色警告,比如下图就是本人在生产环境中遇到过的一次网络分区事故时的截图:
三、网络分区产生
当网络分区发生时,集群内两个或者更多节点认为其它节点crash了。queue、binding、exchange可能会分开创建或删除。通过分区分裂为二,在每个分区内以一个master节点而告终,双方独立行事。其它未定义和怪异的行为可能会发生。
当网络连接恢复时,这种状况依然存在,理解这一点非常重要。集群将继续保持这种分区行为直到你采取行动来解决它。
四、从网络分区中恢复
为了从网络分区中恢复,首先选择一个你最信任的分区。这个分区将被Mnesia当成是可靠的节点来使用,在其它分区内的任何改变都会丢失。
在其它分区内停止所有节点,然后再次启动它们。当它们重新加入集群时,它们将从信任的分区中恢复状态。
最后,你应该也重新启动信任分区内的所有节点以清除警告。
可能更简单的解决方案时停止整个集群,然后再次启动集群,如果确保你第一个启动的节点在信任分区内。
具体步骤如下:
#kill -p(rabbitmq pid)
#rm /var/lib/rabbitmq/m
nesia
#./rabbitmq-server &
#./rabbitmqctr stop_app
#./rabbitmqctr join_cluster rabbit@URL
#./rabbitmactr start_app
OK了。
五、自动处理分区
RabbitMQ也提供了两种方式来自动处理网络分区:pause-minority模式和autoheal模式。(默认行为是ignore模式)。
在pause-minority模式下,RabbitMQ将自动暂停集群节点。根据CAP原理,它选择分区容忍而不是可用性。在网络分区事件发生时,至少在单个分区内节点还继续在运行。
在autoheal模式下,如果一个分区被认为已经发生了,那么RabbitMQ将自动决定获胜分区。它将重启不在获胜分区内的所有节点。拥有大多数客户端连接的分区被认为是获胜分区。
你可以在中通过参数cluster_partition_handling来使能pause_minority或者autoheal模式。
1、应该选择哪种模式
(1)ignore:你的网络是可靠的。所有你的节点在一个机架上,连接到一个交换机上,这个交换机也是通往外部世界的必经之路。
(2)pause_minority:你的网络可靠性很低。
(3)autoheal:你的网络可能不可靠。
2、更多关于暂停少数模式
在pause节点上,Erlang VM将继续运行,但是节点不在任何端口上监听或者做任何网络操作。它们将每秒检测一次看集群内其它节点是否已经出现了,如果出现了再次启动它。
需要注意的是:
(1)节点在启动时不会再进入暂停状态,尽管它们是少数的。
(2)RabbitMQ将暂停集群内的一些节点,这些节点的数目没有严格限制,也就是大于50%。因此在网络分区或者节点faulure事件发生时,在一个两节点的集群内使能pause-minority模式不是个好主意,两个节点将同时暂停。然而,在集群节点大于2时,pause_minority模式可能比ignore模式安全。
关于更多分区的资料也可以参考。
阅读(7978) | 评论(1) | 转发(1) |