第 9 章 一致性与共识 一致性与共识
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
是活着却错了,还是正确却死了?
杰伊-克雷普斯,《关于卡夫卡和杰普逊的几点说明》(2013 年)
正如第 8 章所讨论的,分布式系统中可能会出现很多问题。处理此类故障的最简单方法就是让整个服务失效,并向用户显示错误信息。如果无法接受这种解决方案,我们就需要找到容错的方法,也就是说,即使某些内部组件出现故障,也能保持服务正常运行。
在本章中,我们将举例说明构建容错分布式系统的算法和协议。我们将假设第 8 章中的所有问题都可能发生:数据包可能丢失、重新排序、重复或在网络中任意延迟;时钟充其量只是近似值;节点可能随时暂停(如由于垃圾回收)或崩溃。
构建容错系统的最佳方法是找到一些具有有用保证的通用抽象,将其实现一次,然后让应用程序依赖这些保证。这与我们在第 7 章中使用事务的方法相同:通过使用事务,应用程序可以假装没有崩溃(原子性)、没有其他人并发访问数据库(隔离性)以及存储设备完全可靠(耐用性)。 即使崩溃、竞赛条件和磁盘故障确实会发生,事务抽象也会隐藏这些问题,因此应用程序无需担心。
现在,我们将继续沿着同样的思路,寻找能让应用程序忽略分布式系统中某些问题的抽象概念。例如,分布式系统最重要的抽象之一是共识:即让所有节点就某些事情达成一致。我们将在本章中看到,在网络故障和进程失败的情况下可靠地达成共识是一个令人惊讶的棘手问题。
一旦实现了共识,应用程序就可以将其用于各种目的。例如,假设你有一个使用单领导复制的数据库。如果领导者死亡,需要故障切换到另一个节点,剩余的数据库节点可以使用共识来选举新的领导者。正如"处理节点中断 "中所讨论的,重要的是只有一个领导者,而且所有节点都同意谁是领导者。如果两个节点都认为自己是领导者,这种情况就叫做 "大脑分裂",通常会导致数据丢失。共识的正确实现有助于避免此类问题。
在本章后面的"分布式事务和共识 "部分,我们将研究解决共识和相关问题的算法。但我们首先需要探索分布式系统中可以提供的各种保证和抽象。
我们需要了解哪些事情可以做,哪些事情不可以做:在某些情况下,系统可以容忍故障并继续工作;而在另一些情况下,则不可能做到这一点。 关于哪些事情可以做,哪些事情不可以做,在理论证明和实际应用中都有过深入探讨。我们将在本章概述这些基本限制。
几十年来,分布式系统领域的研究人员一直在研究这些主题,因此有很多资料--我们只能触及表面。在本书中,我们没有篇幅详述形式化模型和证明,因此我们将坚持非正式的直觉。 如果你感兴趣,文献参考可提供大量更深入的内容。
一致性保证
在"复制滞后的问题 "中,我们探讨了复制数据库中出现的一些时间问题。如果在同一时刻查看两个数据库节点,很可能会在两个节点上看到不同的数据,因为写入请求在不同的时间到达不同的节点。无论数据库使用哪种复制方法(单领导、多领导或无领导复制),都会出现这些不一致。
大多数复制数据库至少提供最终一致性,这意味着如果停止向数据库写入数据并等待一段未指定的时间,那么最终所有读取请求都会返回相同的值[1]。换句话说,不一致性是暂时的,最终会自行解决(假设网络中的任何故障最终也会修复)。最终一致性的更好名称可能是 ...