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

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. UVALive6900 Road Repair(树的点分治)

    题目大概说一棵树,树边有费用和收益两个属性,求一条收益和最大的路径满足费用和不超过C. 树上任意两点的路径都可以看成是过某一个子树根的路径,显然树分治. 治的时候要解决的一个问题是,找到费用小于等于某 ...

  2. ViewState与Session

    在asp时代, 大家都知道一个html控件的值,比如input 控件值,当我们把表单提交到服务器后, 页面再刷新回来的时候, input里面的数据已经被清空. 这是因为web的无状态性导致的, 服务端 ...

  3. jQuery Dialog and timepicker显示层的问题

    timepicker官网http://timepicker.co/demos/ 当在dialogue上面调用时间选择时,时间选择的框框被dialogue窗口挡住了. 搜出来的方法说修改css,根本改不 ...

  4. linux查看和修改当前系统时间

    一.查看和修改Linux的时区 1. 查看当前时区 命令 : "date -R" 2. 修改设置Linux服务器时区 方法 A 命令 : "tzselect" ...

  5. 【原】iOS学习之XML与JSON两种数据结构比较和各自底层实现

    1.XML与JSON两种数据结构的优缺点 1> XML 优点:
 格式统一, 符合标准
 容易与其他系统进行远程交互, 数据共享比较方便 
 缺点: XML文件格式文件庞大, 格式复杂, 传输占 ...

  6. iOS之09-特有语法

    1.分类 - Category 1> 基本用途 分类:可以给某个类扩充一些方法(不修改原来的代码) 如何在不改变原来类模型的前提下,给类扩充一些方法? 有2种方式: 继承: 分类(Categot ...

  7. hadoop2.2.0 + hbase 0.94 + hive 0.12 配置记录

    一开始用hadoop2.2.0 + hbase 0.96 + hive 0.12 ,基本全部都配好了.只有在hive中查询hbase的表出错.以直报如下错误: java.io.IOException: ...

  8. [转]CentOS下安装伪分布式Hadoop-1.2.1

    From: http://blog.csdn.net/yinan9/article/details/16805275 环境:CentOS 5.10(虚拟机下) [root@localhost hado ...

  9. CSS z-index 属性的使用方法和层级树的概念

    之前有一篇文章提到过z-index,我们知道只有在元素设置了position部位static时才生效,而且z-index也跟父元素有关系,今天就在ie7遇到类似问题,在网上查了一些资料,发现一篇好文章 ...

  10. javascript new function()

    // 执行的func生成一个空对象,如果有return就会把生成的func对象抛弃function func() {} alert(temp instanceof func) function fun ...