RabbitMQ(七)网络分区
一、引入网络分区的意义
这是有rabbitmq的一致性模型决定的,其主要逻辑如下:
1、所有的操作都是在master上完成,之后再将有影响的操作同步到slave节点上
2、如果客户端连接的是master节点,直接对该节点进行读写操作,然后在同步到slave节点
2、如果客户端连接的是slave节点,RabbitMQ机制也会先将链接路由到master节点上,然后在同步到slave节点
比如确认(Ack)一条消息,先在A节点上,即master节点上确认,之后再转向B节点,进而是C和D节点,最后再D返回Ack之后才真正将这条消息确认,进而标记为可删除。
在这种一致性模型下,如果出现网络波动或者网络延迟等,那么整个复制链的性能就会下降。
引入网络分区就是为了将异常的节点排离出整个分区之外,以确保整个RabbitMQ的性能,待网络情况转好之后再将此节点加入集群之中。
二、网络分区的判定
RabbitMQ中与网络分区的判定相关的是net_ticktime这个参数,默认为60s。
在RabbitMQ集群中的每个broker节点会每隔net_ticktime/4回发送心跳信息到其他节点,如果在连续四次某节点都没有应答,则判定此节点处于down的状态,其余节点可以将此节点剥离出当前分区。
将连续四次的tick时间即为T,那么T的取值范围为 0.75ticktime < T < 1.25ticktime
三、网络分区的恢复策略
网络分区的恢复策略是由cluster_partition_handling参数决定的
1、ignore(默认参数)
ignore的配置是当网络分区的时候,RabbitMQ不会自动做任何处理,即需要手动处理
挑选一个信任的分区,停止其他分区中的节点,然后重新启动这些节点
rabbitmqctl stop_app
rabbitmqctl start_app
2、pause_minority
当发生网络分区时,集群中的节点在观察到某些节点down掉时,会自动检测其自身是否处于少数派(小于或者等于集群中一般的节点数)。
少数派中的节点在分区发生时会自动关闭,当分区结束时又会启动。
这里的关闭是指RabbitMQ application关闭,而Erlang VM并不关闭,这个类似于执行了rabbitmqctl stop_app命令。
处于关闭的节点会每秒检测一次是否可连通到剩余集群中,如果可以则启动自身的应用,相当于执行rabbitmqctl start_app命令。
此模式下,节点数应该为奇数
3、pause_if_all_down, [nodes], ignore|autoheal
在pause_if_all_down模式下,RabbitMQ会自动关闭不能和list中节点通信的节点。
语法为{pause_if_all_down, [nodes], ignore|autoheal},其中[nodes]即为前面所说的list。
如果一个节点与list中的所有节点都无法通信时,自关闭其自身。
如果list中的所有节点都down时,其余节点如果是ok的话,也会根据这个规则去关闭其自身,此时集群中所有的节点会关闭。
如果某节点能够与list中的节点恢复通信,那么会启动其自身的RabbitMQ应用,慢慢的集群可以恢复。
4、autoheal
在autoheal模式下,当认为发生网络分区时,RabbitMQ会自动决定一个获胜的(winning)分区,然后重启不在这个分区中的节点以恢复网络分区。
一个获胜的分区是指客户端连接最多的一个分区。
如果产生一个平局,既有两个或者多个分区的客户端连接数一样多,那么节点数最多的一个分区就是获胜的分区。
如果此时节点数也一样多,将会以一种特殊的方式来挑选获胜分区。
四、选择合适的策略
1、ignore:
你的网络很可靠,所有的节点都在一个机架上,连接在同一个交换机上,这个交换机也连接在WAN上,你不需要冒险而关闭部分节点。(或者适合只有两个节点的集群。)
2、pause_minority
你的网络相对没有那么的可靠。比如你在EC2上建立了三个节点的集群,假设其中一个节点宕了,在这种策略下,剩余的两个节点还可以继续工作,失败的节点可以在恢复之后重新加入集群
3、autoheal
你的网络非常不可靠,你更关心服务的连续性而不是数据的完整性。适合有两个节点的集群。