本文通过梁山好汉的例子来加深理解脑裂问题。
1. 问题描述
Split-brain, 就是在集群环境中,因为异常情况发生后,产生两个子集群。每个子集群都选出一个leader(master)节点。最后互相竞争资源导致故障。
2. 如何解决?
概括起来有几种常见的办法(包括软件,硬件),比如上级干预,内部联络,自己反省,延时处理.
我们假设梁山好汉108人失散了,各54人,宋江卢俊义各率领一半,都以为另外一半挂了,就分别成立了梁山忠义堂。那么双方见面之后,怎么决定谁是老大呢?
a. 上级干预: 使用额外的探测节点,当双方直连断开之后,使用一个约定好的共同节点来探测是否是直连故障。 回到梁山这里,就是两帮好汉都去九天玄女庙,让玄女娘娘指定谁是老大.
b. 专线直连 假如宋江这伙里面有解珍,卢俊义这里有解宝。哥俩之间有特殊心跳联系。所以两帮人知道大家实际都没挂,所以不会分别内部选举而是等待重聚时候再选老大
c. 过半机制 只有某个子集群超过原集群数目一半,才允许选出老大 梁山这里,因为都是54人,都不超过一半,所以都不能选举,只能等待重聚时候选老大
d. 延长选举时间 比如es有参数,据此参数决定从节点访问主节点后如果n秒之内没有回复则默认主节点挂了。这个参数可以调大。 梁山这里,就是约好了如果失散之后1个月联系不上,才能选举老大。现在调整为1年之后才能选举。那么1年之内其实重聚的可能性很大。
3. 具体案例
a. Zookeeper采用“过半机制”解决
在领导者选举过程中,如果某台zkserver获得了超过半数的选票,则此zkServer就可以成为leader了。 关键代码:
return (set.size() > n/2); n 表示旧集群中zkServer参与者的数目 set标是故障之后,本子集群的参与者个数。
关键点是:必须超过原集群的半数才能成为leader。这就保证了无论怎么出现故障分裂,所以子集群中或者都没有leader,或者只有一个leader(该子集群超过半数了)。比如原来6台,n/2=3。如果分裂成两个3台的子集群,则都没有leader,如果一个4台,一个2台,则4台的会成为leader.
b. ElasticSearch有调节参数
discovery.zen.ping_timeout:3
discovery.zen.minimum_master_nodes:1
该参数的意思是,当具备成为主节点的从节点的个数满足这个数字且都认为主节点挂了则会进行选举产生新的主节点。 例如:es集群有三个从节点有资格成为主节点,这时这三个节点都认为主节点挂了则会进行选举,此时如果这个参数的值是4则不会进行选举。 我们可以适当的把这个值改大,减少出现脑裂的概率,官方给出的建议是(n/2)+1。
4. 参考:
https://my.oschina.net/u/236698/blog/525413
https://mp.weixin.qq.com/s/VlkK_Lb-ZlGcYi-QfHC22Q