Raft论文 寻找一种易于理解的共识算法(扩展版)(下)

46 阅读28分钟

6 Cluster membership changes 集群成员变更

到目前为止,我们认为集群的配置(参与共识算法的服务器集)是固定的。 实际上,我们需要偶尔改变集群的配置,例如在服务器崩溃时替换它或者改变复制的程度。 尽管这些可以通过暂停整个集群,更新配置,重启来实现,但是这会导致变更时集群不可用。 除此之外,如果存在人工的步骤,这也会有操作失误的风险。 为了避免这些问题,我们决定自动化配置编程的过程并将其整合到Raft共识算法中。

为了保证配置变更的过程是安全的,在变更期间不能存在两个Leader在同一任期同时当选的情况。 不幸的是,任何服务器直接从旧配置变更为新配置的方案都是不安全的。 原子化的一次性变更是不现实的,因此整个集群在变更期间划分成两个独立的主体是有可能的。

Figure 10

Figure 10:直接从一种配置切换到另一种配置时不安全的,因为不同的服务器会在不同的时间切换。例如,集群从3扩增到5台机器。不幸的是,在一个时间点上,两个不同的Leader可以在同一个任期中当选,一个是旧配置的主体选出的(ColdC_{old}),一个是新配置的主体选出的(CnewC_{new})。

为了确保安全性,配置变更必须使用两阶段方法。 目前有多种两阶段的实现方式。例如有些系统在第一阶段禁用旧配置,使其无法处理客户端请求;然后再第二阶段启动新配置。 在Raft中,集群首先切换到一个称之为joint consensus的过渡配置;一旦共同共识已经commit,系统再切换到新配置。 共同共识结合了新旧配置:

  • 日志条目被复制给集群中的所有服务器,无论新旧。
  • 新旧配置的服务器都能竞选Leader。
  • 达成一致(针对选举和提交)需要分别在两种配置上获得大多数的支持。

Figure 11

Figure 11:配置变更的时间线。虚线表示已经创建的但尚未提交的配置项,实现表示最新提交的配置项。 Leader首先在自己的的日志中创建C-new,C-old的配置条目,然后提交到C-old-new中。然后创建C-new条目并提交给C-new中的大多数,这样就不存在C-new和C-old可以同时决策的时间点。

共同共识允许独立的服务器在不破坏安全性的前提下,在不同的时间点进行配置转换。此外共同共识允许集群持续响应客户端请求,即使在配置变更中。

集群配置在复制日志中通过特殊的条目来存储和通信;Figure 11展示了配置变更的过程。 当Leader节点接收到一个变更配置从ColdC_{old}CnewC_{new}的请求,它会将共同共识的配置(图中的ColdnewC_{old-new})存储为日志条目,并使用前面描述的机制复制该条目。 一旦一个服务器在日志中新增了配置条目,它在未来的决策中都使用该配置(服务器总是使用其日志中的最新配置,无论该条目是否已经提交)。 这意味着Leader会使用Cold,newC_{old,new}的规则来决定Cold,newC_{old, new}的体质条目何时commit。 如果Leader崩溃了,一个新的Leader会在ColdC_{old}或者Cold,newC_{old,new}的配置下被选举,这取决于赢得选举的Candidate是否已经收到了Cold,newC_{old,new}配置。 在任何情况下,CnewC_{new}配置在这一时期都不能做出单方面的决策。

一旦Cold,newC_{old,new}配置已经提交,未经另一个配置的允许,CnewC_{new}ColdC_{old}都不能做出决策,并且Leader完全特性保证了只有拥有Cold,newC_{old,new}的节点才能被选举为Leader。 这个时候,Leader创建一条关于CnewC_{new}配置的日志条目并复制给其他机器就是安全的。 同样,该配置将会在每台服务器上生效。 当新配置已经在CnewC_{new}的规则下提交,旧配置就不重要了,同时未应用新配置的服务器就可以被关闭了。 Figure 11中,ColdC_{old}CnewC_{new}没有任何机会做出单方决策;这确保了安全性。

重新配置还有三个问题需要解决。 第一个问题,新的服务器可能最初没有存储任何条目。如果以这种状态加入到集群中,那么他们需要相当长的时间来同步,而且在这段时间里不能提交新的条目。 为了便面这种间隔,Raft在配置变更之前引入一个额外的阶段,在这个阶段,新的服务器以没有投票权的身份加入到集群(Leader拷贝日志给它们,但是不考虑它们时大多数)。 一旦新的服务器和其他的机器同步了,就可以向上述一样处理配置变更了。 第二个问题,集群Leader可能不是新配置中的一部分。在这种情况下,Leader一旦提交完CnewC_{new}日志就会变成Follower状态。这意味着有一段时间(提交CnewC_{new}时)Leader管理着集群但是不包括它自己;他复制日志但不将自己作为大多数之一。 Leader变更将会在CnewC_{new}提交时发生,因为这是新配置可以独立工作的最早时间(总是能在新配置下选出Leader)。 在此之前,只能从旧配置下选举Leader。

第三个问题,被移除的服务器(不在CnewC_{new}中的服务器)可能会破坏集群。这些服务器将不会收到心跳,所以当选举超时时,它们就会开始新的一轮选举。 它们会发送RequestVote RPCs(携带新的任期号),这会导致当前的Leader回退为Follower状态(因为集群中没有收到CnewC_{new}的节点开启了新的任期号)。 新的Leader最终被选出来,但是被移除的服务器会再次超时,然后再次重复这个过程,导致可用性很差。

为了避免这个问题,当服务器确认当前的Leader存在时,会忽略RequestVoteRPCs请求。 准确来说,当服务器接在当前的最小选举超时时间内收到一个RequestVoteRPC,他不会更新任期号或者投出选票。 这不会影响正常的选举,每个服务器在开始一次选举之前,必须至少等待一个最小选举超时时间。 然而,这有利于避免被移除的服务器扰乱集群:如果Leader能够和集群保持心跳,那么它就不会被更大的任期号废黜。

7 Log campaction 日志压缩

Raft的日志在正常的运作中会不断增长,但是在实际体统中,日志是不能无限长增长的。 随着日志增长,它会占用更多的空间,花费更多的时间重置。 如果没有某些机制来清除日志中堆积的陈旧信息,那么最终会导致可用性出现问题。

快照时最简单的压缩方式。 在快照中,整个系统的状态都以快照的形式写入到稳定存储中,然后在这之前的所有日志全部清除。快照在Chubby和Zookeeper中均有使用,接下来会介绍Raft中的快照技术。

Figure 12

Figure 12:一个服务器用一个新快照来替代日志中的已提交条目(index1~5),快照存储了当前的状态(x,y)。日志的最后索引位置和任期号都包含在其中。

增量压缩,例如日志清理或者日志结构合并树,都是可行的。 这些方法每次只对一小部分的数据操作,这样可以分散压缩的负载压力。 它们先选择一个已经累积了许多被删除和覆盖的对象的数据区域,然后将该区域的存活对象重写地更加紧凑,并释放这块区域。 和简单操作整个数据集的快照相比,这需要更复杂的额外机制。 状态机可以实现LSM树,使用和快照相同的接口,但是日志清除可能需要修改Raft了。

Figure12展示了Raft中快照的基本思想。 每个服务器可以独立创建快照,只包括已经被提交的日志。主要工作是将状态机的当前状态写入快照中。 Raft也包含一些少量的元数据在快照中:last included index指的是被快照取代的最后条目在日志中的索引值(状态机最后应用的日志),last included term指的是该条目的任期号。保留这些是为了支持快照后紧接着的第一个AppendEntriesRPCs的一致性检查,因为这个条目需要前一个条目的索引值和日期号。 为了支持成员变更,快照中也将最后一次配置作为最后一个条目存储下来。 一旦服务器完成快照的写入,它可以删除最后索引之前的所有日志和快照。

尽管通常服务器都是独立的创建快照,Leader必须偶尔发送快照给一些落后的Follower。 这通常发生在Leader已经丢弃了它需要发送给Follower的下一个日志条目时。 幸运的是,这种情况不是常规操作:一个与Leader保持同步的Follower通常持有这个条目。 然而一个运行缓慢的Follower或者刚加入集群的服务器将不会持有这个条目。 这时让这个Follower更新到最新状态的方式就是通过网络将快照发送给它。

Figure 13

Figure 13:InstallSnapshotRPC的概要。快照被分割成小块进行传输;每个分块都给予Follower生命的信号,所以Follower可以重置选举超时计时器。

Leader使用一种名为InstallSnapshotRPC的方式来发送快照给太落后的Follower;见Figure 13。当Follower通过这种RPC接收到快照时,他必须自己决定对于它的现存日志如何处理。 通常快照会包括接受者的日志中不存在的信息。在这种情况下,Follower会丢弃其整个日志;全部被快照取代,并且可能包含于快照冲突的未提交条目。 如果接受的快照是自己日志的前缀部分(由于网络重传或者错误),那么快照包含的条目将会被清除,但是快照后的条目仍然有效,会被保留。

这种快照的方式违背了Raft的强Leader原则,因为Follower可以在Leader不知道的情况下创建快照。 但是我们认为这种背离是正确的。 Leader的存在,是为了解决在达成共识时带来的冲突,但是创建快照时,共识已经达成,已经不存在冲突了。 数据仍然是从Leader流向Follower,只不过Follower重新组织了数据而已。

我们思考过另一种基于Leader的方法,即只有Leader创建快照,然后发送给所有的Follower。 但是,这样做会有两个弊端。 第一,发送快照会浪费网络带宽并且延缓快照处理的时间按。每一个Follwer既然已经拥有了生产快照的信息,显然在自己本地创建快照要比通过网络接受更加有效。 第二,Leader的实现将会更加复杂。例如,Leader需要发送快照的同时并行请求将新的日志条目发送给Follower,这样才不会阻塞新的客户端请求。

还有两个问题影响了快照的性能。 第一个,服务器必须决定何时创建快照。如果快照创建过于频繁,这会浪费大量的磁盘带宽;如果快照创建频率太低,它就要承受耗尽存储的风险,同时增加了日志重建的时间。一个简单的策略就是在日志达到以字节为单位的固定大小时就创建快照。如果将该大小设置为明显大于快照的预期大小,那么用于快照的磁盘带宽开销将很小。 第二个,就是写入快照通常需要花费一段不少的时间,而且我们希望这不要影响正常的操作。解决的方式时使用写入时复制技术(copy-on-write),这样可以接受新的更新而不会影响正在写入的快照。例如,使用函数式数据结构的状态机天然支持这样的功能。此外,操作系统的copy-on-write技术(如Linux中的fork)可以被用于创建完整的状态机内存快照(我们就是这样实现的)。

8 Client interaction 客户端交互

这一节将介绍客户端是如何于Raft交互的,包括客户端如何发现集群Leader和Raft如何支持线性化的语义的。 这些问题对于所有的基于共识的系统都是存在的,并且Raft 的解决方式和其他系统相似。

Raft的客户端发送所有的请求给Leader。当客户端启动时,它会随机挑选一个服务器进行通信。若果客户端第一次挑选的服务器不是Leader,那么这个服务器会拒绝请求,并提供它最新的Leader信息(AppendEntriesRPC中有)。如果Leader已经崩溃了,那么请求会超时;客户端之后会重试。

Raft的目标是实现线性化的语义(每一次操作立即执行,只执行一次,在他调用和收到回复之间)。但是,如上述,Raft可能会多次执行同一条指令:例如,Leader在提交日志条目后,在响应客户端前崩溃了,那么客户端就会和新的Leader重试这条命令,导致这条命令吧被再次执行。 解决方式就是客户端对于每条指令赋予一个唯一的序列号。然后状态机跟踪每条指定最新的序列号和其响应。如果收到一条已被执行的序列号,那么可以直接返回结果。

只读的操作可以不需要记录日志而直接处理。但是在没有额外措施的情况下,这可能会有风险读取脏数据,因为响应客户端请求的Leader可能不知道它已经不再是Leader了。 线性化的读取一定不能返回脏数据,Raft需要两个额外措施来保证不使用日志的情况下实现这一点。 首先Leader必须有关于已经提交的日志的最新信息,但是在它任期刚开始时,它可能不知道哪些信息时已被提交的。因此,在它任期开始时,它会提交一条空的日志。(日志匹配机制) 第二,Leader处理只读的请求时必须检查自己是否已被废黜(产生了新Leader)。Raft通过让Leader在响应只读请求直接先和集群中的大多数节点交换一次心跳信息来应对这个问题。或者,Leader可以依靠心跳机制来提供一种租约的机制,但是这种方式依赖时间来保证安全性(它假设时间误差是有界的)。

9 Implementation and evaluation 算法实现和评估

我们已经为RAMCloud实现了Raft算法作为存储配置信息的复制状态机的一部分,并且帮助RAMCloud协调故障转移。 这个实现大约2000行左右的C++代码,其中不包括测试,注释和空行。 这些代码是开源的。同时也有大约25个独立的第三方开源实现(针对不同的场景)。当然,很多企业已经部署了基于Raft的系统。

这一节会从三个方面评估Raft:可理解性,正确性,性能。

9.1 Understandability 可理解性

为了和 Paxos 比较 Raft 算法的可理解性,我们针对高层次的本科生和研究生,在斯坦福大学的高级操作系统课程和加州大学伯克利分校的分布式计算课程上,进行了一次学习的实验。 我们分别安排了针对 Raft 和 Paxos 的视频课程,并准备了相应的小测验。Raft 的视频讲课覆盖了这篇论文的所有内容除了日志压缩;Paxos 讲课包含了足够的资料来创建一个等价的复制状态机,包括单决策 Paxos,多决策 Paxos,重新配置和一些实际系统需要的性能优化(例如Leader选举)。 小测验测试一些对算法的基本理解和解释一些边角的示例。每个学生都是看完第一个视频,回答相应的测试,再看第二个视频,回答相应的测试。 大约有一半的学生先进行 Paxos 部分,然后另一半先进行 Raft 部分,这是为了说明两者从第一部分的算法学习中获得的表现和经验的差异。 我们计算参加人员的每一个小测验的得分来看参与者是否在 Raft 算法上更加容易理解。

我们尽可能的使得 Paxos 和 Raft 的比较更加公平。这个实验偏爱 Paxos 表现在两个方面:43 个参加者中有 15 个人在之前有一些 Paxos 的经验,并且 Paxos 的视频要长 14%。 如Table 1总结的那样,我们采取了一些措施来减轻这种潜在的偏见。我们所有的材料都可供审查。

关心缓和偏见采取的手段可供查看的材料
相同的讲课质量两者使用同一个讲师。Paxos 使用的是现在很多大学里经常使用的。Paxos 会长 14%。视频
相同的测验难度问题以难度分组,在两个测验里成对出现。小测验
公平评分使用评价量规。随机顺序打分,两个测验交替进行。评价量规(rubric)

Table 1:考虑到可能会存在的偏见,对于每种情况的解决方法,和相应的材料。

参加者平均在 Raft 的测验中比 Paxos 高 4.9 分(总分 60,那么 Raft 的平均得分是 25.7,而 Paxos 是 20.8);Figure 14 展示了每个参与者的得分。 配置t-检验(又称student‘s t-test)表明,在 95% 的可信度下,真实的 Raft 分数分布至少比 Paxos 高 2.5 分。

Figure 14

Figure 14:一个散点图表示了 43 个学生在 Paxos 和 Raft 的小测验中的成绩。在对角线之上的点表示在 Raft 获得了更高分数的学生。

我们也建立了一个线性回归模型来预测一个新的学生的测验成绩,基于以下三个因素:他们使用的是哪个小测验,之前对 Paxos 的经验,和学习算法的顺序。模型预测,对小测验的选择会产生 12.5 分的差别。 这显著的高于之前的 4.9 分,因为很多学生在之前都已经有了对于 Paxos 的经验,这相当明显的帮助 Paxos,对 Raft 就没什么太大影响了。 但是奇怪的是,模型预测对于先进行 Paxos 小测验的人而言,Raft的得分低了6.3分; 虽然我们不知道为什么,这似乎在统计上是有意义的。

我们同时也在测验之后调查了参与者,他们认为哪个算法更加容易实现和解释;这个的结果在Figure 15 上。压倒性的结果表明 Raft 算法更加容易实现和解释(41 人中的 33个)。 但是,这种自己报告的结果不如参与者的成绩更加可信,并且参与者可能因为我们的 Raft 更加易于理解的假说而产生偏见。

Figure 15

Figure 15:通过一个 5 分制的问题,参与者(左边)被问哪个算法他们觉得在一个高效正确的系统里更容易实现,右边被问哪个更容易向学生解释。

9.2 Correctness 正确性

在第 5 节,我们已经制定了正式的规范,和对一致性机制的安全性证明。这个正式规范使用 TLA+ 规范语言使图Figure 2中总结的信息非常清晰。 它长约400行,并作为证明的主题。同时对于任何想实现 Raft 的人也是十分有用的。 我们通过 TLA 证明系统非常机械的证明了日志完全特性。然而,这个证明依赖的约束前提还没有被机械证明(例如,我们还没有证明规范的类型安全)。而且,我们已经写了一个非正式的证明关于状态机安全性是完备的,并且是相当清晰的(大约 3500 个词)。

9.3 Performance 性能

Raft 和其他一致性算法例如 Paxos 有着差不多的性能。在性能方面,最重要的是,当领导人被选举成功时,什么时候复制新的日志条目。Raft 通过很少数量的消息包(一轮从Leader到集群大多数机器的消息)就达成了这个目的。 同时,进一步提升 Raft 的性能也是可行的。例如,很容易通过支持批量操作和管道操作来提高吞吐量和降低延迟。对于其他一致性算法已经提出过很多性能优化方案;其中有很多也可以应用到 Raft 中来,但是我们暂时把这个问题放到未来的工作中去。

我们使用我们自己的 Raft 实现来衡量 Raft 的Leader选举的性能并且回答两个问题。首先,Leader选举的过程收敛是否快速?第二,在Leader宕机之后,最小的系统宕机时间是多久?

Figure 16

Figure 16:发现并替换一个已经崩溃的Leader的时间。上面的图考察了在选举超时时间上的随机化程度,下面的图考察了最小选举超时时间。 每条线代表了 1000 次实验(除了 150-150 毫秒只试了 100 次),和相应的确定的选举超时时间。 例如,150-155 毫秒意思是,选举超时时间从这个区间范围内随机选择并确定下来。这个实验在一个拥有 5 个节点的集群上进行,其广播时延大约是 15 毫秒。对于 9 个节点的集群,结果也差不多。

为了衡量Leader选举,我们反复的使一个拥有五个节点的服务器集群的Leader宕机,并计算需要多久才能发现Leader已经宕机并选出一个新的Leader(见Figure 16)。 为了构建一个最坏的场景,在每一的尝试里,服务器都有不同长度的日志,意味着有些Candidate是没有成为Leader的资格的。 另外,为了促成选票瓜分的情况,我们的测试脚本在终止Leader之前同步的发送了一次心跳广播(这大约和Leader在崩溃前复制一个新的日志给其他机器很像)。Leader均匀的随机的在心跳间隔里宕机,也就是最小选举超时时间的一半。因此,最小宕机时间大约就是最小选举超时时间的一半。

Figure 16 中上面的图表明,只需要在选举超时时间上使用很少的随机化就可以大大避免选票被瓜分的情况。 在没有随机化的情况下,在我们的测试里,选举过程往往都需要花费超过 10 秒钟由于太多的选票瓜分的情况。仅仅增加 5 毫秒的随机化时间,就大大的改善了选举过程,现在平均的宕机时间只有 287 毫秒。 增加更多的随机化时间可以大大改善最坏情况:通过增加 50 毫秒的随机化时间,最坏的完成情况(1000 次尝试)只要 513 毫秒。

Figure 16 中下面的图显示,通过减少选举超时时间可以减少系统的宕机时间。在选举超时时间为 12-24 毫秒的情况下,只需要平均 35 毫秒就可以选举出新的Leader(最长的一次花费了 152 毫秒)。然而,进一步降低选举超时时间的话就会违反 Raft 的时间不等式需求: 在选举新Leader之前,Leader就很难发送完心跳包。这会导致没有意义的Leader改变并降低了系统整体的可用性。 我们建议使用更为保守的选举超时时间,比如 150-300 毫秒;这样的时间不大可能导致没有意义的Leader改变,而且依然提供不错的可用性。

10 Related work 相关工作

已经有很多关于一致性算法的工作被发表出来,其中很多都可以归到下面的类别中:

  • Lamport 关于 Paxos 的原始描述,和尝试描述的更清晰。
  • 关于 Paxos 的更详尽的描述,补充遗漏的细节并修改算法,使得可以提供更加容易的实现基础。
  • 实现一致性算法的系统,例如 Chubby,ZooKeeper 和 Spanner。对于 Chubby 和 Spanner 的算法并没有公开发表其技术细节,尽管他们都声称是基于 Paxos 的。ZooKeeper 的算法细节已经发表,但是和 Paxos 着实有着很大的差别。
  • Paxos 可以应用的性能优化。
  • Oki 和 Liskov 的 Viewstamped Replication(VR),一种和 Paxos 差不多的替代算法。原始的算法描述和分布式传输协议耦合在了一起,但是核心的一致性算法在最近的更新里被分离了出来。VR 使用了一种基于领导人的方法,和 Raft 有很多相似之处。

Raft 和 Paxos 最大的不同之处就在于 Raft 的强领导特性:Raft 使用Leader选举作为一致性协议里必不可少的部分,并且将尽可能多的功能集中到了Leader身上。 这样就可以使得算法更加容易理解。例如,在 Paxos 中,Leader选举和基本的一致性协议是正交的:Leader选举仅仅是性能优化的手段,而且不是一致性所必须要求的。 但是,这样就增加了多余的机制:Paxos 同时包含了针对基本一致性要求的两阶段提交协议和针对Leader选举的独立的机制。 相比较而言,Raft 就直接将Leader选举纳入到一致性算法中,并作为两阶段一致性的第一步。这样就减少了很多机制。

像 Raft 一样,VR 和 ZooKeeper 也是基于Leader的,因此他们也拥有一些 Raft 的优点。 但是,Raft 比 VR 和 ZooKeeper 拥有更少的机制因为 Raft 尽可能的减少了非Leader的功能。例如,Raft 中日志条目都遵循着从Leader发送给其他人这一个方向:附加条目 RPC 是向外发送的。 在 VR 中,日志条目的流动是双向的(Leader可以在选举过程中接收日志);这就导致了额外的机制和复杂性。根据 ZooKeeper 公开的资料看,它的日志条目也是双向传输的,但是它的实现更像 Raft。

和上述我们提及的其他基于一致性的日志复制算法中,Raft 的消息类型更少。例如,我们数了一下 VR 和 ZooKeeper 使用的用来基本一致性需要和成员改变的消息数(排除了日志压缩和客户端交互,因为这些都比较独立且和算法关系不大)。 VR 和 ZooKeeper 都分别定义了 10 种不同的消息类型,相对的,Raft 只有 4 种消息类型(两种 RPC 请求和对应的响应)。Raft 的消息都稍微比其他算法的要信息量大,但是都很简单。 另外,VR 和 ZooKeeper 都在Leader改变时传输了整个日志;所以为了能够实践中使用,额外的消息类型就很必要了。

Raft 的强Leader模型简化了整个算法,但是同时也排斥了一些性能优化的方法。 例如,平等主义 Paxos (EPaxos)在某些没有Leader的情况下可以达到很高的性能。 平等主义 Paxos 充分发挥了在状态机指令中的交换性。任何服务器都可以在一轮通信下就提交指令,除非其他指令同时被提出了。 然而,如果指令都是并发的被提出,并且互相之间不通信沟通,那么 EPaxos 就需要额外的一轮通信。 因为任何服务器都可以提交指令,所以 EPaxos 在服务器之间的负载均衡做的很好,并且很容易在 WAN 网络环境下获得很低的延迟。但是,他在 Paxos 上增加了非常明显的复杂性。

一些集群成员变换的方法已经被提出或者在其他的工作中被实现,包括 Lamport 的原始的讨论,VR 和 SMART。 我们选择使用共同一致的方法因为他对一致性协议的其他部分影响很小,这样我们只需要很少的一些机制就可以实现成员变换。 Lamport 的基于 α 的方法之所以没有被 Raft 选择是因为它假设在没有Leader的情况下也可以达到一致性。和 VR 和 SMART 相比较,Raft 的重新配置算法可以在不限制正常请求处理的情况下进行;相比较的,VR 需要停止所有的处理过程,SMART 引入了一个和 α 类似的方法,限制了请求处理的数量。 Raft 的方法同时也需要更少的额外机制来实现,和 VR、SMART 比较而言。

11 Conclusion 总结

算法的设计通常会把正确性,效率或者简洁作为主要的目标。尽管这些都是很有意义的目标,但是我们相信,可理解性也是一样的重要。 在开发者把算法应用到实际的系统中之前,这些目标没有一个会被实现,这些都会必然的偏离发表时的形式。 除非开发人员对这个算法有着很深的理解并且有着直观的感觉,否则将会对他们而言很难在实现的时候保持原有期望的特性。

在这篇论文中,我们尝试解决分布式一致性问题,但是一个广为接受但是十分令人费解的算法 Paxos 已经困扰了无数学生和开发者很多年了。 我们创造了一种新的算法 Raft,显而易见的比 Paxos 要容易理解。我们同时也相信,Raft 也可以为实际的实现提供坚实的基础。 把可理解性作为设计的目标改变了我们设计 Raft 的方式;随着设计的进展,我们发现自己重复使用了一些技术,比如分解问题和简化状态空间。 这些技术不仅提升了 Raft 的可理解性,同时也使我们坚信其正确性。

12 Acknowledgments 致谢

这项研究必须感谢以下人员的支持:Ali Ghodsi,David Mazieres,和伯克利 CS 294-91 课程、斯坦福 CS 240 课程的学生。Scott Klemmer 帮我们设计了用户调查,Nelson Ray 建议我们进行统计学的分析。在用户调查时使用的关于 Paxos 的幻灯片很大一部分是从 Lorenzo Alvisi 的幻灯片上借鉴过来的。特别的,非常感谢 DavidMazieres 和 Ezra Hoch,他们找到了 Raft 中一些难以发现的漏洞。许多人提供了关于这篇论文十分有用的反馈和用户调查材料,包括 Ed Bugnion,Michael Chan,Hugues Evrard,Daniel Giffin,Arjun Gopalan,Jon Howell,Vimalkumar Jeyakumar,Ankita Kejriwal,Aleksandar Kracun,Amit Levy,Joel Martin,Satoshi Matsushita,Oleg Pesok,David Ramos,Robbert van Renesse,Mendel Rosenblum,Nicolas Schiper,Deian Stefan,Andrew Stone,Ryan Stutsman,David Terei,Stephen Yang,Matei Zaharia 以及 24 位匿名的会议审查人员(可能有重复),并且特别感谢我们的领导人 Eddie Kohler。Werner Vogels 发了一条早期草稿链接的推特,给 Raft 带来了极大的关注。我们的工作由 Gigascale 系统研究中心和 Multiscale 系统研究中心给予支持,这两个研究中心由关注中心研究程序资金支持,一个是半导体研究公司的程序,由 STARnet 支持,一个半导体研究公司的程序由 MARCO 和 DARPA 支持,在国家科学基金会的 0963859 号批准,并且获得了来自 Facebook,Google,Mellanox,NEC,NetApp,SAP 和 Samsung 的支持。Diego Ongaro 由 Junglee 公司,斯坦福的毕业团体支持。

PS:第9-12节的翻译直接引用了github.com/maemual/raf…