Background
为了变化raft集群,我们可以选择:.停在旧配置,然后再上线新配置 。但是这个会导致整个集群变得不可用,同时手动修改也会到来问题。
所以我们采用热变更
这也导致了安全性的问题,变更过程有可能导致两个leader出现。
变更方式:
一次只变更一个
如果限制每次只变更一个节点,那么就能保证“新、旧集合的quorum集合是有重合的”,由于有重合,这样就能保证新旧两个集群的集合不会选出不同的leader,就能间接保证安全性。
证明
加入节点前 加入节点后
(n / 2 + 1 ) + (((n + 1)) / 2 + 1)
开始时是偶数:n = 2k k + 1 + k + 1 = 2k + 2 > 2k + 1不可能
开始时是奇数:n = 2k + 1 k + 1 + k + 2 = 2k + 3 > 2k + 2 不可能
同时变更多个,采用二阶段的策略
注意:配置日志是立即生效的,不需要等待
Cnew和Cold的并集作为一个配置,然后把先把Cold的通过leader提交,这个配置立即生效,在提交之前的话,可能leader会fail,然后被别的Cold别的节点变成leader,然后截断日志,可能就会回退到Cold。所以说在提交之前Cold可以make decison alone。另一种情况是提交之后的话,要new和old两个分别大多数同样才能提交。那么这样的话,因为选举限制的缘故,那么新老配置都不能独立做出决定,因为肯定都是有新配置的变为leader,能看到并集的个数的,要达到并集个数的大多数才能提交。同理对于新配置,看到的是新配置的个数,有一种情况是提交失败,一种情况是提交成功,也就是意味着在新配置在新配置节点上大多数同意了,同时也意味着联合共识不可能了,保障了不会有两个leader。第一个阶段,提交并集配置到新旧大多数节点。这样保障了不会有两个leader,因为leader必然要新配置,新配置要达到并集大多数。第二阶段:提交new的配置到new的大多数节点,这样保障了之前的联合共识不可能达成,就一个leader。i
issue:(我还是好奇这个新加入节点的配置。。。,感觉是不是要没配置啊,然后等别人发给他配置才能变成candidate,不然第一阶段就有可能产生两个leader啊,希望懂哥可以在评论区指点江山)
Failover
我们来看看Joint Consensus算法,在变更过程中如果出错,是如何failover选出新leader的。
第一阶段,这时候选出来的leader只有可能有两种情况,还是旧的C_Old节点集合,或者已经收到了{C_Old,C_New}节点集合:
- 只有C_Old节点集合的节点:由于这时候这个leader并没有第一阶段提交的{C_Old,C_New}节点集合变更,因此那些已有{C_Old,C_New}节点集合的follower这部分的日志将被截断,成员变更失败,回退回C_Old集合。
- 有{C_Old,C_New}节点集合的节点:这意味这个leader已经有第一阶段提交的{C_Old,C_New}节点集合变更,可以继续将未完成的成员变更流程走完。
类似的,也可以去推导一下在第二阶段出现leader宕机时,选出来的leader只可能具备两种情况,但是这两种情况都不可能选出多个leader。
提交安全性
为了安全性,Raft在进行集群变更操作时,无论是“单次变更一个节点”还是“一次变更多个节点”,在不同的阶段都不能有重叠(overlap)的情况出现,因为重叠意味着可能违反前面提到的安全性。比如将一个集群节点集合从{1,2,3}变更为{1,4,5},如果使用这两种方式,步骤分别是:
- 单次变更一个节点:{1,2,3}->{1,2,3,4} (增加节点4)->{1,2,3,4,5} (增加节点5)->{1,3,4,5} (删除节点2)-> {1,4,5} (删除节点3)。
- 单次变更多个节点:{1,2,3}(C_Old)-> {1,2,3,4,5}({C_Old,C_New})-> {1,4,5}(C_Old,C_New)。
可以看到,无论采用哪一种方式,都会有多个步骤。由leader来决定当前的步骤,其判断的标准是:前一步修改的日志,是否已经被提交(半数以上同意)。所以,如果成员变更类的日志在提交之后才生效的话,leader就需要再多一个步骤:
- 首先确认日志已经被提交到半数以上节点。
- 在这之后,再确认这个成员变更已经在节点上生效。
而后面的这个确认,是可以避免的。因为根据前面failover
部分的分析,无论哪一种情况出现,即便在变更的过程中leader宕机,也不会出现选出多个leader的情况。
于是,对于成员变更类的日志来说,Raft的规则是:
- 多次提交不能重叠(overlap),即如果当前已经有还未提交的成员变更日志,在它提交之前不允许提交新的成员变更修改。
- 成员变更的生效,无需等待提交,每个节点在收到这类日志的时候,就能马上修改本节点上的成员为最新的这个配置。
参考资料:周刊(第13期):重读Raft论文中的集群成员变更算法(一):理论篇 - codedump的网络日志