单个成员变更
联合共识依赖两个阶段来实现成员变更算法,在工程实现中却有难度。于是有研究者 发现了一个更加简单的方案,即不允许一次变更多个成员,而是一次只能从集群中添加或 删除一个成员,称为单个成员变更(Single-Server Changes)。在这个限制条件下,我们可 以使用 Raft Log 的形式,在日志协商阶段使新的成员配置在集群中得以应用,无须引入额 外的机制。
联合共识之所以分为两个阶段,是因为对需要变更的成员没有过多的要求,为了避免 在变更过程中拥有 Cold 和 Cnew 配置的成员形成没有交集的多数派,因此引入了中间状态。要求这个中间状态的决策条件是得到 Qold 和 Qnew 的支持,这是比“多数派”更强的约束, 变相地引入了一个相交的实体(中间状态),其目的就是为了保证两个决策集合一定存在相 交的成员,进而保证算法的正确性。
联合共识对需要变更的成员没有过多的要求,甚至在保证集群可用的情况下,允许替 换所有成员,但是在实际场景中并不经常有变更大量成员的需求,并且两阶段的逻辑在工 程实现上比较困难。后来发现了一个更简单的方法,即不允许因为成员变更而产生不同的 多数派。因此,Raft 限制了变更条件:一次只能从集群中添加或删除一个成员。这样便能 保证 Qold 和 Qnew 之间一定存在相交的成员,如下图所示。
这种重叠阻止了集群分区,保证一定存在重叠的成员,因此当只添加或删除单个成员 时,直接切换到新的配置是安全的。利用这一点,不需要复杂的联合共识即可安全地更改 集群成员身份。
成员变更的bug
在一些极端情况下,成员变更方案曾引发过比较激烈的关于安全性的讨论。在成员变 更过程中,如果频繁切换 Leader,可能会丢失已提交的日志。Diego Ongaro 曾公开讨论过 这个 Bug1,但这个 Bug 仅限于单个成员变更,联合共识不受影响。
Diego Ongaro 在论坛中提出了 3 个反例来重现这个 Bug,其本质都是新成员配置被提 交后,旧成员配置仍有可能被提交,这里以向集群中增加一个成员同时删除另一个成员为 例进行说明。如下图所示,存在一个集群,其初始配置为 C1={S1, S2, S3, S4},先后收 到两个成员变更请求 C2 和 C3,C2 为集群增加成员 S5,C3 为集群删除成员 S1。具体配置 是 C2={S1, S2, S3, S4, S5},C3={ S2, S3, S4}。
T2 时刻:S1 在任期 term 为 1 时晋升为 Leader。
T3 时刻:收到成员变更请求 C2,并将其复制到 S1 和 S5 中。
T4 时刻:S1 宕机,S2 在任期 term 为 2 时晋升为 Leader。
T5 时刻:收到成员变更请求 C3,并将其复制到 S2 和 S3 中。
T6 时刻:收到事务请求 Div,并将其复制到 S2 和 S3 中,然后在获得多数派的支持后提交该日志项。
T7 时刻:S2 宕机,S1 在任期 term 为 3 时晋升为 Leader,其多数派为{S1, S4, S5}。
T8 时刻:S1 将 C2 复制到所有成员中,但是 S1 没有拥有 Div 的日志项,因此 Div最终会被抛弃
笔者给这种情况取了一个形象的名字为穿越时间的脑裂,即两个不同时间的Leader 拥有互不重叠的两个多数派。出现这种情况的原因是,Leader 一上任就开始执行成员变更, 并使用新的成员配置协商日志项。
解决这个问题的方案是 Leader 上任之后,必须在当前任期中提交一条日志项,然后才 能执行成员变更。这一动作的目的是使下一个晋升 Leader 的多数派与该日志项的多数派存 在一个重叠的成员,这样就有效限制了后续 Leader 晋升的成员范围。
接着上面的示例,L2 在晋升 Leader 之后,协商并提交一条 Noop 的日志项,其{S2, S3, S4}包含该日志项,那么在 term 为 3 的任期中,S1 不能再晋升 Leader,能晋升 Leader 的成员只能是 S3,最终 Div 日志项才得以延续保存。
为什么只能是 S3 晋升 Leader 呢?具体情况如下:
S1 配置为 C2={S1, S2, S3, S4, S5},多数派数量为 3,会给它投票的成员为{S1, S5}。
S2 宕机。
S3 配置为 C3={ S2, S3, S4},多数派数量为 2,会给它投票的成员为{S3, S4}。
S4 配置为 C1={S1, S2, S3, S4},多数派数量为 3,会给它投票的成员为{S1, S4}。
S5 配置为 C2={S1, S2, S3, S4, S5},多数派数量为 3,会给它投票的成员为{S1, S5}。
新书预售享7.5折
尽管联合共识能有效的解决成员变更面临的问题,但是由于在工程实现中仍有难度。值得高兴的是,有一本全面、系统的剖析共识算法的书籍《深入理解分布式共识算法》即将出版。书中不仅详细描述了Raft的协商过程,对成员变更、工程实现都做了详细的解说,包含了:
单个成员变更
对称网络分区、非对称网络分区
线性一致性的实现
并行协商的优化
安全性证明
Raft工程实现
....
尽管这些内容已经足够吸引人了,但这仅仅是书中的冰山一角,全书涵盖了当前流行的大部分共识算法和分布式事务解决方案,例如:Paxos、ZAB、Raft、Fast Paxos、EPaxos、以及各类Paxos的变种算法。
除了内容全面,本书特色包含了:
多维度阐述:对每一种算法都按照“背景知识 → 运行过程 → 算法模拟 → 证明脉络”的多维度境界,思路清晰,易于理解。
对比总结:针对各种算法总结对比,分析各自的优缺点,并结合当下流行的经典类库和中间件的源码,逐步印证算法的实现过程。
注重实践:精心准备了20多道练习题,可以帮助读者进一步加深对相关算法的理解。
图文并茂:精心绘制120余幅示意图,帮助读者更直观地理解各种算法的运行过程。
视频教学:对重点和难点内容有针对性地录制了教学视频,帮助读者高效、直观地学习
本书赞誉
本书获得了多位Apache和蚂蚁金服的多位专家等人力荐。