本文为RAFT一致性算法论文的译文,原文是《In search of an Understandable Consensus Algorithm (Extended Version)》,作者为 Diego Ongaro 和 John Ousterhout 。
3 Paxos 的缺陷
在过去的十年中,Leslie Lamport 的 Paxos 协议几乎成为一致性的代名词:这种协议被广泛地用于教授一致性算法,同时也是多数一致性的实现的起点。首先,Paxos 定义了能够在单个决策中(例如某个复制日志条目)达成一致的协议。我们称这个子集为单一决策 Paxos(single-decree Paxos )。随后,Paxos 结合多个前述协议的实例,达成一系列决策(multi-Paxos),如一个日志条目。 Paxos 能够确保安全性和活跃度,并且支持集群成员的调整。他的正确性已被证明,并且在通常情况下都是有效的。
然而,Paxos 有两个明显的缺陷:
-
难于理解:Paxos 的说明晦涩难懂;只有少数人,通过大量的努力,才能全面地理解。为了解决这个问题,已经有人试图通过更简洁的方式解释 Paxos。这些解释的关注点在于单一决策子集,然而这个工作仍然极具挑战性。在一项针对NSDI 2012 与会人员的非正式调查中,我们发现很少有人能够适应 Paxos,即使是经验丰富的研究人员。我们挣扎于 Paxos,难以理解如此复杂的协议,除非阅读几份简化后的 Paxos 说明文档,并且自行设计 Paxos 协议的替代品。整个过程会耗费几乎一年的时间。
我们推测 Paxos 之所以晦涩难懂,原因在于它选择以单一决策子集作为基础。单一决策 Paxos 精密且微妙:它分成两个阶段,每个阶段没有简单直观的解释,也无法被独立地理解。因此,人们很难对单一决策协议的工作方式产生直观的认识。多决策 Paxos (multi-Paxos)的组织规则又引入了大量额外的复杂性和微妙性。我们相信可以通过其他更简明的方式来解决多决策(如一个日志条目)的一致性问题;
没有一个良好的先例:Paxos 没有提供一个构建实际实现的良好基础。其中一个原因是,目前没有一个广泛认同的多决策 Paxos 算法。Lamport 的论述更多的是关于单一决策 Paxos ;他只是对多决策 Paxos 给出了可能的实现思路,但是对很多细节并未提及。有些人已经对补充和优化 Paxos 进行了多次尝试,但是实现方式却与 Lamport 的思路大相径庭。Chubby 等系统实现了类 Paxos 算法,但是多数案例的具体实现并未公布。
此外,Paxos 的体系结构不利于在实际应用中构建系统;这是单一决策分解(single-decree decomposition)的另一个结果。例如,独立地选择日志条目的集合并将它们合并到有序日志中几乎没有任何好处,这只会徒增复杂性。围绕着一个日志,设计一个新条目有约束地被有序追加到的系统更加简单有效。另一个问题是,Paxos 在内核中使用对称的 P2P 方法(尽管它最终针对性能优化提出了弱形式的领导结构)。这种方式在只需要做一个决策的简单情景中很有效,但是实际应用中只有少数系统使用这种方式。当需要做出一系列的决策时,更简单快速的方法是,选举一个 leader,让 leader 协调做出决策。
因此,实际应用中的系统与 Paxos 几乎没有相似之处。每个实现过程始于 Paxos,当发现实现它过于困难时,便开发出一套完全不同的体系结构。这非常耗时而且容易出错,并且 Paxos 的难于理解又加剧了这个问题。Paxos 的公式也许利于证明它的正确性,但是实际实现与 Paxos 的差别如此之大,以至于这些证明并没有多大价值。如下来自 Chubby 作者的这段话做出了诠释:
Paxos 算法的描述与现实世界系统的需求有着巨大差异。。。系统的最终实现将会基于未被证明的协议。
由于这些问题的存在,我们得出结论:Paxos 不适用于构建系统或用于教学。鉴于一致性在大规模软件系统中的重要性,我们决定尝试设计一个能够替代 Paxos 的更好的一致性算法。这项研究的成果便是 Raft。
4 易于理解的设计
在设计 Raft 时我们有几个目标:
- 它必须提供一个完整的实际的系统实现的基础,以显著降低开发者的设计工作;
- 在所有情况下,它必须是安全的,并且在典型的操作场景下是可用的;
- 在通常的操作中,它必须是有效的;
- 而最重要也是最难的目标是易于理解,它必须能被大多数人轻松地理解;
- 此外,它应当尽可能的直观,以使系统开发者在实际实现中应用。
在设计 Raft 的过程中,我们需要在大量的备选方案中做出选择。在这些情况下,我们基于易理解性权衡备选方案:解释备选方案时的难度(例如,方案的状态空间有多复杂,是否有些许微妙的含义),读者完整的理解方案的方法和含义的难度。
我们意识到这种分析方式有很强的主观性,但是我们使用了两项普适的技术来解决这个问题:
- 问题分解:我们尽可能的将问题分解为很多子问题,以使问题更便于解决、解释和理解。例如,在 Raft 中,我们分解出 leader 选取,日志复制,安全性和成员变更。
- 简化状态空间:通过减少需要考虑的状态来简化状态空间,使系统更紧凑并尽可能消除不确定性。特别的,日志中不允许有空洞,并且 Raft 限制了引起日志不一致的可能情况。尽管在多数情况下,我们都要尽可能地消除不确定性,但是在某些情况下,不确定性的存在却可以换来易理解性。尤其是随机化方法引入了不确定性,但同时也通过使用相近的方式处理所有可能的选择来简化状态空间。因此,我们采用随机化方法来简化 Raft 的 leader 选取算法。