集群为了保证数据一致性,在同步数据的同时也会通过节点之间的心跳通信来保证对方存活。那如果集群节点通信异常会发生什么,系统如何保障正常提供服务,使用何种策略回复呢?

rabbitmq提供的处理脑裂的方法有两种:autoheal、pause_minority.

autoheal指的是在出现脑裂且恢复时采用分区中与客户端连接数最多的一个分区来作为winner,并将所有的losers分区重启。

pause_miniroty指的是在出现脑裂后判断自己是否为众数者majority,即自己所在分区是否为总节点数的一半以上length(AliveNodes) / length(Nodes) > 0.5,如果属于众数者则正常工作,否则做rabbit:stop()操作,并以1秒周期查询自己是否属于众数者。

下面主要介绍下autoheal的实现原理。

首先在rabbit.erl中根据启动流程中可以看到

-rabbit_boot_step({rabbit_node_monitor,
[{description, "node monitor"},
{mfa, {rabbit_sup, start_restartable_child,
[rabbit_node_monitor]}},
{requires, [rabbit_alarm, guid_generator]},
{enables, core_initialized}]}).

启动并注册系统事件来获取(rabbit_node_monitor.erl)

 {ok, _} = mnesia:subscribe(system),

当环境中出现分区恢复后,mneisa会收到{nodeup, Node},并根据此节点来获取远端有记录mnesia down过的节点,当两个节点都认为对方出现过down的情况下,即会发送{inconsistent_database, Context, Node}系统事件【1】,并在所有节点都起来的情况下开始autoheal, rabbit_node_monitor.erl。

handle_info({mnesia_system_event,
{inconsistent_database, running_partitioned_network, Node}},
State = #state{partitions = Partitions,
monitors = Monitors}) ->
%% We will not get a node_up from this node - yet we should treat it as
%% up (mostly).
State1 = case pmon:is_monitored({rabbit, Node}, Monitors) of
true -> State;
false -> State#state{
monitors = pmon:monitor({rabbit, Node}, Monitors)}
end,
ok = handle_live_rabbit(Node),
Partitions1 = lists:usort([Node | Partitions]),
{noreply, maybe_autoheal(State1#state{partitions = Partitions1})};
maybe_autoheal(State = #state{autoheal = AState}) ->
case all_nodes_up() of
true -> State#state{autoheal = rabbit_autoheal:maybe_start(AState)};
false -> State
end.

利用autoheal处理脑裂的时候,先在节点中找到一个leader,然后这个leader来公正地决定胜负。

maybe_start(not_healing) ->
case enabled() of
true -> Leader = leader(),
send(Leader, {request_start, node()}),
rabbit_log:info("Autoheal request sent to ~p~n", [Leader]),
not_healing;
false -> not_healing
end;

针对获取到的所有分区开始做决定以选择分区中的winner和losers,决策原则是根据各个分区中所拥有的连接数的个数来确定的,如果连接数相同,则选择分区内节点最多的分区。

make_decision(AllPartitions) ->
Sorted = lists:sort([{partition_value(P), P} || P <- AllPartitions]),
[[Winner | _] | Rest] = lists:reverse([P || {_, P} <- Sorted]),
{Winner, lists:append(Rest)}. partition_value(Partition) ->
Connections = [Res || Node <- Partition,
Res <- [rpc:call(Node, rabbit_networking,
connections_local, [])],
is_list(Res)],
{length(lists:append(Connections)), length(Partition)}.

之后loser会做重启,可能会因此而导致数据丢失。

参考文献

1. mnesia之inconsistent_database. http://my.oschina.net/hncscwc/blog/174416

2. rabbitmq对network partition的处理. http://my.oschina.net/hncscwc/blog/174417

rabbitmq之partitions的更多相关文章

  1. RabbitMQ Network Partitions的预警和处理策略

    网络分区的意义 RabbitMQ的模型类似交换机模型,且采用erlang这种电信网络方面的专用语言实现.RabbitMQ集群是不能跨LAN部署(如果要WAN部署需要采用专门的插件)的,也就是基于网络情 ...

  2. RabbitMQ Network Partitions

    Clustering and Network Partitions RabbitMQ clusters do not tolerate network partitions well. If you ...

  3. RabbitMQ Network Partitions 处理策略

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 网络分区的意义 RabbitMQ的模型 ...

  4. RabbitMQ配置文件

    配置文件Config 在Web的可视化管理界面中可以看到一些文件的路径 比如 Config文件的地址 数据库存放的文件夹 log文件的地址 进入到这个文件夹会发现有这些文件,其中example是con ...

  5. rabbitmq.config配置文件

    %% -*- mode: erlang -*-%% -------------------------------------------------------------------------- ...

  6. RabbitMQ 集群与网络分区(理论知识)

    关于network partition网络设备故障导致的网络分裂.比如,存在A\B\C\D\E五个节点,A\B处于同一子网,B\C\D处于另外一子网,中间通过交换机相连.若两个子网间的交换机故障了即发 ...

  7. 【rabbitmq】RabbitMQ 集群与网络分区

    网络分区(network partitions) 官网-网络分区 网络设备故障导致的网络分裂.比如,存在A\B\C\D\E五个节点,A\B处于同一子网,B\C\D处于另外一子网,中间通过交换机相连.若 ...

  8. RabbitMQ脑裂问题解决方案调查

    现象: RabbitMQ GUI上显示 Network partition detectedMnesia reports that this RabbitMQ cluster has experien ...

  9. Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践

    目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ?   RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...

随机推荐

  1. 笔记本做wifi热点

    你可以开启windows 7的隐藏功能:虚拟WiFi和SoftAP(即虚拟无线AP),就可以让电脑变成无线路由器,实现共享上网.点开始 所有程序 命令提示符右键管理员身份运行命令提示符 运行命令:ne ...

  2. Theano深度学习结构分析

    Reference:Theano入门三部曲 http://deeplearning.net/tutorial/logreg.html  (Softmax回归) http://deeplearning. ...

  3. POJ 1222 (开关问题+高斯消元法)

    题目链接: http://poj.org/problem?id=1222 题目大意:一堆开关,或开或关.每个开关按下后,周围4个方向开关反转.问使最后所有开关都关闭的,开关按法.0表示不按,1表示按. ...

  4. android 第三方 Im

    1.阿里百川 单聊.群聊.客服能力集成,仅需花费4小时,不收费,0成本接入,让App轻松拥有沟通能力,历经多次双十一考验,消息到达率100%,全年可用性高达99.99%,登录异常提醒,木马钓鱼网站监测 ...

  5. 应用程序间跳转 (友盟SSO 授权 与系统自带的分享)

    应用程序间跳转的应用场景 使用第三方用户登录,如微信登录,返回用户名和密码 需要用户授权,返回到调用程序,同时返回授权的用户名 应用程序推广,跳转到itunes并显示指定app下载页 第三方支付,跳转 ...

  6. Jquery实现下拉联动表单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. POJ 1127 Jack Straws(计算几何)

    题目链接 抄的模版,居然1Y了.就是简单的线段相交+并查集. #include <iostream> #include <cstring> #include <cstdi ...

  8. 开发android过程中eclipse闪退解决

    有一次eclipse崩溃了,然后再双击就无法打开了.换了几个版本也是如此. 后来找到了这个方法:删除文件 [workspace]/.metadata/.plugins/org.eclipse.e4.w ...

  9. vs2013的单元测试 第一部分

    这次的vs2013的单元测试我学到了许多,虽然到现在我还是不能完成,但是我也学到了许多. 首先,在vs2013中先安装Unit Test Generator,如图所示: 这个是进行单元测试重要的一个插 ...

  10. js-小效果-手风琴

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...