这几天看了不上网上关于RAFT的成员变更的介绍,基本上是对原论文的翻译,毫无解释可言。因此准备结合自己的理解,通俗易懂地介绍一下成员变更的过程。这里面主要有2种方法,是本人搜集了一些论文总结思考所得。
想象在我们的共识算法中,现在有3个节点,我们若想增加至5个节点,一般如何处理?
常用的方法是让所有服务器停机,再进行更新。那为什么要这么做呢?
这里引用论文中的图片。如图,我们在原有集群中有Server1, Server2, Server3三个服务器。现在想加入Server4和Server5。若Server3首先进行了更新,这个时候就出现了问题。
在Cnew新的配置中,5个服务器的大多数为3,在Cold旧的配置文件中,3个服务器的大多数为2。而现在就可能出现有2个Leader的情况。Server1请求Server2给自己投票,便获得了大多数投票。Server4请求Server3和Server5投票,也获得了自己配置文件中的大多数投票。(这里省略了自己给自己投票的描述)。
在同一个集群中,我们处理客户的请求,需要保持最终结果一致性。若出现2个Leader,究竟听谁的命令呢?因此这将无法维持结果一致性。
所以,目前大多数企业的操作方式是让服务停止,然后对其进行更新,待更新完毕后,重新启动集群。
因此有人提出了以下这个方案,我们一个一个来。那接下来看看能不能解决问题。
如图,节点D加入集群,告知Leader,Leader随后对本地进行更新,并通知其他节点。
这里主要分析极端情况,如图,若A首先更新,之后A掉线,会不会出现2个Leader?
①对于D而言,他若想成为Leader需要集群中的3个节点同意才可以完成竞选,而B,C在旧的配置中无法察觉D的存在,也不会给他投票。
②对于A,他本身就是Leader,若他竞选,需要得到B,C其中一位投票才能继续成为Leader。此外,竞选成功后,他会继续执行B,C的扩充指令,直至完成更新。
③对于B,C他们可以互相投票,成为Leader,但若投票之后,A无法成为Leader,因此不会出现2个Leader同时出现的情况。
该方法主要针对一次扩充多个节点,以及替换节点的情况。这里主要分析,一次扩充多个节点。
现在,C节点进行了中间态,原文称为(Cold_new)。在该状态,若想成为Leader需要新旧集群中的大多数节点都给他投票才行。即(A,B,C)U (A,B, C, D, E)中大多数,这两个条件都需要满足。
我们分析下图的情况:
①A,B可以互相投票称为Leader。
②C需要获得A,B中的一票,且获得A,B,D,E中的两票才能称为Leader。因此②与①互斥。
③D,E若想成为Leader需要A,B,C,D,E中的大多数给他投票,但A,B作为旧集群的节点,并不会给新集群的节点投票。
但不妨假设可以给他们投票,D,E需要A,B,C中的一票:
因此这里需要禁止C给新集群中的节点投票。(这个是我自己想的,原文并没有明说。)
当旧集群中大多数节点更新之后,原论文称此时只有过渡态的节点可以被选为Leader。因此这里我们又可以推出过渡态无法给旧节点投票。不过个人认为即使可以给旧节点投票,也不会造成分歧,具体分析和上一种情形类似。
①A成为Leader后也可以继续给集群服务,并进行自我更新。
②同样,D,E同样无法得到A,B,C的投票。
③因此只有B,C可以获得大多数节点投票成为Leader。
当大多数节点成为过渡态后,可以向新的配置文件更新。如图,此时B已经更新为新的配置文件。
①此时B,D,E可以竞选成功(接受同为新集群的节点投票),成为Leader。
②C也可以竞选成功,但需获得(B,D,E中的一位),因此与①互斥。
③A则无法竞选成功。