Consensus Bridging Theory and Practice(一)

1,417 阅读8分钟

本文是对Diego Ongaro论文CONSENSUS: BRIDGING THEORY AND PRACTICE的翻译

第一章 介绍

今天的数据中心系统和应用运行在多变的环境中。它们通过添加服务器资源扩大规模,服务器数量根据场景增长或缩小。服务或网络的失败是常态:现代数据中心中,每年大约有2%-4%的概率会发生磁盘损坏和服务器崩溃,每天大约有几十条网络线路会出现故障。

所以,系统必须在把处理服务器的新增和失效作为日常运维必须要考虑的一环。系统需要能够在秒级响应变化并自动适应这些变化;能够被人感知到的维护窗口通常是不能被接受的。这是当今计算机系统的主要挑战;错误处理,协调配合,服务发现,以及配置管理都是在这种场景下的难题。

幸运的是,分布式共识算法能够帮助面对这些挑战。共识的含义是,一组机器作为一个内聚的整体(共识组),当其中的一些成员发生故障时,也能够正常对外提供服务。在一组满足一致性条件的机器中,错误处理必须遵从一定的原则。共识组是具有高可用性和高稳定性的,其他的软件系统会使用共识组作为他们自身错误容忍机制的基础。所以,共识算法在构建大规模软件系统中扮演着重要角色。

在很多系统中,仍然存在利用共识原理能够解决的问题。一些大规模系统依然受到单点协调服务器崩溃的限制(如HDFS)。还有一些系统引入了ad hoc复制算法来处理错误,尽管这种处理方式是不安全的(如MongoDB,Redis)。新系统能够使用的共识算法实现的组件很少(ZooKeeper是最流行的),迫使系统开发人员只有一种选择或者只能自己开发。

那些选择自己实现共识算法的开发者们通常会考虑Paxos。在过去的二十年,Paxos算法是共识算法的标准:多数共识算法的实现都以Paxos算法为基础或受到它思想的影响,Paxos也成为了共识算法的教科书。

不幸的是,尽管有过很多简化的尝试,Paxos算法依旧很难理解。而且,要在实际环境中应用Paxos算法构建系统需要对Paxos算法的架构做复杂的改造,而且需要开发一些扩展,而这些扩展的细节实际上是没有包含在Paxos算法的公开发表中的。所以无论是学生党还是开发者,都较难上手Paxos。

另外两个为人熟知的共识算法是Viewstamped Replication以及Zab,后者被用在ZooKeeper中。尽管我们相信,这两个算法在构建系统方面比Paxos有更好的结构,但是它们也不是为了更容易让人理解作为目标而设计的。要理解并实现这两个算法的成本依旧很高。

因为理解和实现非常复杂,开发者往往绕开共识的实现,这使得他们的系统需要牺牲容错性或一致性,或者开发自己的ad hoc算法,这通常会导致安全性问题。

我们试图找到一个不同于Paxos的算法,这种算法容易理解,并且足够完整。能够在生产环境中实现并且有较好的性能表现。这个算法要能够描述清楚接受消息后系统的反应,并能够描述出整个系统的状态变化。算法要能够保证一致性,也要提供可用性。

Raft是这篇文章提出的解决方案。Raft算法使用了一些手段,使得算法更容易理解,包括分解(Raft算法把leader选举,日志复制和安全做了分割)以及状态的减少(减少了不确定性程度和服务器之间产生不一致的路径)。我们也会考虑构建一个基于共识系统的其他问题。

这篇论文将从以下方面介绍Raft算法:

  1. Raft算法的设计,实现以及价值。Raft算法和现有的一致性算法有相似之处,但是更容易理解。Raft算法也有一些新颖的特性,比如,使用了更强形式的leader,简化了日志复制的管理,并且使得Raft协议更容易理解。
  2. Raft算法的leader选举机制的设计,实现以及价值。虽然很多其他的一致性算法并没有指定一个特殊的leader选举算法,Raft引入了一个特定的leader选举算法,这个算法涉及到随机化的计时器。心跳检测是任何共识算法都需要的,Raft算法在心跳机制上做了少量调整,同时能够简单而迅速的解决冲突。我们在功能和性能上研究了这种leader选举算法,结论是这种简单的方式能够在实践环境中表现良好。它一般能够选择出集群单向网络延时二十倍一下的结点作为leader。
  3. Raft算法的集群成员变更机制的设计和实现。Raft允许在同一时间为集群增加或移除一台服务器;这种操作很容易保证安全,因为在操作期间至少有一台服务器的状态和大多数服务器重叠。更加复杂的变化被认为是一系列单独服务器的变化。Raft允许集群在变更期间持续被操作,集群成员变更可以在基础的共识算法的基础上做一点扩展而实现。
  4. 对一个完整的共识系统所需要的其他组件的全面的讨论和实现,包括客户端集成,以及log压缩。虽然这些部分对于Raft算法来说并不是核心,但是对这些组件的讨论有助于对算法的理解以及在实际环境中构建系统。我们实现了一个完整的以共识为基础的系统,方便定位和阐述相关的设计。
  5. 关于安全性的证明以及Raft算法的正式规范。正式规范的精确度有助于仔细地推理算法,并澄清算法非正式描述中的细节。安全性的证明有助于构建对Raft算法正确性的信心。通过阐述扩展对于安全性的影响,也可以对希望扩展Raft算法的用户提供帮助。

我们已经以开源的形式实现了许多在本文中讨论的设计,实现的名称叫做LogCabin。LogCabin是我们测试有关Raft的一些想法的平台,也是一种证实我们理解构建一个完整的,真实的系统过程中的问题的途径。实现在第十章中被详细描述。

文章的剩余部分介绍了复制状态机,讨论了Paxos算法的优势和劣势;介绍了Raft算法在集群成员变更,以及日志压缩方面的扩展,描述了客户端和Raft算法的交互模式;评估了Raft算法在可理解性,正确性以及leader选举和日志复制的效率;讨论了关联工作。

第二章 目标

共识在错误容忍的系统中是一个基本问题:不同的服务器如何在共享的状态上达成一致,即便在可能会失败的场景下。究竟如何在保证高可用的前提下,也保证一致性呢,这是很多需要提供高可用性,且在一致性上无法折中的系统都面临的问题;共识算法是几乎所有强一致性的大规模存储系统中都要考虑的问题。2.1节描述了如何创建一个复制状态机,这是共识算法的典型使用场景,复制状态机是错误容忍系统中的一个多功能模块;2.2节介绍了复制状态机在更大系统中的不同使用方式;2.3节讨论了Paxos共识协议的问题,也是Raft协议要解决的问题。

2.1 用复制状态机实现错误容忍

共识算法一般出现在复制状态机的上下文中。状态机归属于一组机器,这些机器计算一个相同状态的拷贝,并且不受宕机影响。如在2.2节中所述,复制状态机被用来解决各种分布式系统中的错误容忍问题。Chubby和ZooKeeper是两个使用复制状态机的例子,它们有一个分层级的K-V存储系统,用来存储小规模的配置数据。除了Get和Put等基础操作,它们也提供了一些同步原语,如compare-and-swap,为需要并发的客户端能够安全的进行同步和协调提供支持。

复制状态机的一种典型的实现方式是利用可复制日志,如图2.1所示。

图2.1