9. 一致性与共识

9. 一致性与共识 - 图1

好死不如赖活着 —— Jay Kreps, 关于Kafka与 Jepsen的若干笔记 (2013)


​ 正如第8章所讨论的,分布式系统中的许多事情可能会出错。处理这种故障的最简单方法是简单地让整个服务失效,并向用户显示错误消息。如果无法接受这个解决方案,我们就需要找到容错的方法—— 即使某些内部组件出现故障,服务也能正常运行。

​ 在本章中,我们将讨论构建容错分布式系统的算法和协议的一些例子。我们将假设第8章的所有问题都可能发生:网络中的数据包可能会丢失,重新排序,重复递送或任意延迟;时钟只是尽其所能地近似;且节点可以暂停(例如,由于垃圾收集)或随时崩溃。

​ 构建容错系统的最好方法,是找到一些带有实用保证的通用抽象,实现一次,然后让应用依赖这些保证。这与第7章中的事务处理方法相同:通过使用事务,应用可以假装没有崩溃(原子性),没有其他人同时访问数据库(隔离),存储设备是完全可靠的(持久性)。即使发生崩溃,竞态条件和磁盘故障,事务抽象隐藏了这些问题,因此应用不必担心它们。

​ 现在我们将继续沿着同样的路线前进,寻求可以让应用忽略分布式系统部分问题的抽象概念。例如,分布式系统最重要的抽象之一就是共识(consensus)就是让所有的节点对某件事达成一致。正如我们在本章中将会看到的那样,尽管存在网络故障和流程故障,可靠地达成共识是一个令人惊讶的棘手问题。

​ 一旦达成共识,应用可以将其用于各种目的。例如,假设你有一个单主复制的数据库。如果主库挂点,并且需要故障切换到另一个节点,剩余的数据库节点可以使用共识来选举新的领导者。正如在“处理节点宕机”中所讨论的那样,重要的是只有一个领导者,且所有的节点都认同其领导。如果两个节点都认为自己是领导者,这种情况被称为脑裂(split brain),且经常导致数据丢失。正确实现共识有助于避免这种问题。

​ 在本章后面的“分布式事务和共识”中,我们将研究解决共识和相关问题的算法。但首先,我们首先需要探索可以在分布式系统中提供的保证和抽象的范围。

​ 我们需要了解可以做什么和不可以做什么的范围:在某些情况下,系统可以容忍故障并继续工作;在其他情况下,这是不可能的。我们将深入研究什么可能而什么不可能的限制,既通过理论证明,也通过实际实现。我们将在本章中概述这些基本限制。

​ 分布式系统领域的研究人员几十年来一直在研究这些主题,所以有很多资料—— 我们只能介绍一些皮毛。在本书中,我们没有空间去详细介绍形式模型和证明的细节,所以我们将坚持非正式的直觉。如果你有兴趣,参考文献可以提供更多的深度。