From 84aace63ea42069b4b2e1f557ab540c95ee48398 Mon Sep 17 00:00:00 2001 From: Vonng Date: Thu, 8 Mar 2018 19:05:01 +0800 Subject: [PATCH] =?UTF-8?q?ch9=20=E5=88=9D=E7=BF=BB30%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- ddia/ch8.md | 2 - ddia/ch9.md | 633 ++++++++++++++++++++-------------------------------- 3 files changed, 244 insertions(+), 395 deletions(-) diff --git a/README.md b/README.md index efbc395..0d94ad6 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,8 @@ | 第五章:复制 | 初翻 | | | 第六章:分片 | 初翻 | | | 第七章:事务 | **精翻 80%** | | -| 第八章:分布式系统的麻烦 | **初翻** | | -| 第九章:一致性与共识 | 机翻 | 进行中 | +| 第八章:分布式系统中的问题 | **初翻** | | +| 第九章:一致性与共识 | 机翻 | 进行中,初翻30% | | 第三部分:前言 | 机翻 | | | 第十章:批处理 | 机翻 | | | 第十一章:流处理 | 机翻 | | diff --git a/ddia/ch8.md b/ddia/ch8.md index 181f863..8d73fe7 100644 --- a/ddia/ch8.md +++ b/ddia/ch8.md @@ -344,8 +344,6 @@ NTP同步是否能足够准确,以至于这种不正确的排序不会发生 一个有趣的例外是Spanner中的Google TrueTime API 【41】,它明确地报告了本地时钟的置信区间。当你询问当前时间时,你会得到两个值:[最早,最晚],这是最早可能的时间戳和最晚可能的时间戳。在不确定性估计的基础上,时钟知道当前的实际时间落在该区间内。间隔的宽度取决于自从本地石英钟最后与更精确的时钟源同步以来已经过了多长时间。 -$\wedge$ - #### 全局快照的同步时钟 在“[快照隔离和可重复读取](ch7.md#快照隔离和可重复读取)”中,我们讨论了快照隔离,这是数据库中非常有用的功能,需要支持小型快速读写事务和大型长时间运行的只读事务,用于备份或分析)。它允许只读事务看到特定时间点的处于一致状态的数据库,且不会锁定和干扰读写事务。 diff --git a/ddia/ch9.md b/ddia/ch9.md index 75e3c79..91e3388 100644 --- a/ddia/ch9.md +++ b/ddia/ch9.md @@ -11,96 +11,95 @@ [TOC] -正如第8章所讨论的,分布式系统中的许多事情可能会出错。处理这种故障的最简单方法是简单地让整个服务失败,并向用户显示错误消息。如果这个解决方案是不可接受的,我们需要找到容忍错误的方法——即保持服务正常运行,即使某些内部组件出现故障。 +正如[第8章](ch8.md)所讨论的,分布式系统中的许多事情可能会出错。处理这种故障的最简单方法是简单地让整个服务失效,并向用户显示错误消息。如果无法接受这个解决方案,我们就需要找到容错的方法——即使某些内部组件出现故障,服务也能正常运行。 -在本章中,我们将讨论构建容错分布式系统的算法和协议的一些例子。我们将假设第8章的所有问题都可能发生:网络中的数据包可能会丢失,重新排序,重复或任意延迟;时钟近似于最好;并且节点可以暂停(例如,由于垃圾收集)或随时崩溃。 +在本章中,我们将讨论构建容错分布式系统的算法和协议的一些例子。我们将假设[第8章](ch8.md)的所有问题都可能发生:网络中的数据包可能会丢失,重新排序,重复递送或任意延迟;时钟只是尽其所能地近似;且节点可以暂停(例如,由于垃圾收集)或随时崩溃。 -构建容错系统的最好方法是找到一些有用的保证的通用抽象,实现一次,然后让应用程序依靠这些保证。这与第7章中的事务处理方法相同:通过使用事务,应用程序可以假装没有崩溃(原子性),没有其他人同时访问数据库(隔离),存储设备是完全可靠的(耐用性)。即使发生崩溃,竞态条件和磁盘故障,事务抽象隐藏了这些问题,以便应用程序不必担心它们。 +构建容错系统的最好方法,是找到一些带有实用保证的通用抽象,实现一次,然后让应用依赖这些保证。这与[第7章](ch7.md)中的事务处理方法相同:通过使用事务,应用可以假装没有崩溃(原子性),没有其他人同时访问数据库(隔离),存储设备是完全可靠的(持久性)。即使发生崩溃,竞态条件和磁盘故障,事务抽象隐藏了这些问题,因此应用程序不必担心它们。 -现在我们将继续沿着同样的路线前进,寻求可以让应用程序忽略分布式系统的一些问题的抽象概念。例如,分布式系统最重要的抽象之一就是**共识(consensus)**:就是让所有的节点对某个事物达成一致。正如我们在本章中将会看到的那样,尽管存在网络故障和流程故障,可靠地达成共识是一个令人惊讶的棘手问题。 +现在我们将继续沿着同样的路线前进,寻求可以让应用忽略分布式系统部分问题的抽象概念。例如,分布式系统最重要的抽象之一就是**共识(consensus)**:**就是让所有的节点对某件事达成一致**。正如我们在本章中将会看到的那样,尽管存在网络故障和流程故障,可靠地达成共识是一个令人惊讶的棘手问题。 -一旦达成共识,应用程序可以将其用于各种目的。例如,假设你有一个单主复制的数据库。如果主库挂点,并且需要故障转移到另一个节点,剩余的数据库节点可以使用共识来选举新的领导者。正如在“[处理节点中断]()”中所讨论的那样,重要的是只有一个领导者,并且所有的节点都同意领导者是谁。如果两个节点都认为他们是领导者,那么这种情况被称为**脑裂(split brain)**,并且经常导致数据丢失。正确实现共识有助于避免这种问题。 +一旦达成共识,应用程序可以将其用于各种目的。例如,假设你有一个单主复制的数据库。如果主库挂点,并且需要故障转移到另一个节点,剩余的数据库节点可以使用共识来选举新的领导者。正如在“[处理节点宕机](ch5.md#处理节点宕机)”中所讨论的那样,重要的是只有一个领导者,并且所有的节点都认同其为领导。如果两个节点都认为自己是领导者,这种情况被称为**脑裂(split brain)**,且经常导致数据丢失。正确实现共识有助于避免这种问题。 -在本章后面的第352页的“分布式事务和共识”中,我们将研究解决共识和相关问题的算法。但首先,我们首先需要探索可以在分布式系统中提供的保证和抽象的范围。 +在本章后面的“[分布式事务和共识](#分布式事务和共识)”中,我们将研究解决共识和相关问题的算法。但首先,我们首先需要探索可以在分布式系统中提供的保证和抽象的范围。 -我们需要了解可以做什么和不可以做什么的范围:在某些情况下,系统可以容忍故障并继续工作;在其他情况下,这是不可能的。在理论证明和实际实施中都深入探索了什么是和不可能的限制。我们将在本章中概述这些基本限制。 +我们需要了解可以做什么和不可以做什么的范围:在某些情况下,系统可以容忍故障并继续工作;在其他情况下,这是不可能的。我们将深入研究什么可能而什么不可能的限制,既通过理论证明,也通过实际实现。我们将在本章中概述这些基本限制。 -分布式系统领域的研究人员几十年来一直在研究这些主题,所以有很多材料 - 我们只能在表面上划伤。在本书中,我们没有空间去详细介绍形式模型和证明的细节,所以我们将坚持非正式的直觉。如果您有兴趣,参考文献可以提供更多的深度。 +分布式系统领域的研究人员几十年来一直在研究这些主题,所以有很多资料——我们只能介绍一些皮毛。在本书中,我们没有空间去详细介绍形式模型和证明的细节,所以我们将坚持非正式的直觉。如果你有兴趣,参考文献可以提供更多的深度。 ## 一致性保证 -在第161页中的“复制滞后问题”中,我们查看了复制数据库中发生的一些计时问题。如果您在同一时刻查看两个数据库节点,则可能会在两个节点上看到不同的数据,因为写请求在不同的时间到达不同的节点。无论数据库使用何种复制方法(单引导程序,多引导程序或无引导程序复制),都会出现这些不一致情况。 +在“[复制延迟问题](ch5.md#复制延迟问题)”中,我们看到了数据库复制中发生的一些时序问题。如果你在同一时刻查看两个数据库节点,则可能在两个节点上看到不同的数据,因为写请求在不同的时间到达不同的节点。无论数据库使用何种复制方法(单引导程序,多引导程序或无引导程序复制),都会出现这些不一致情况。 -大多数复制的数据库至少提供了最终的一致性,这意味着如果你停止向数据库写入数据并等待一段不确定的时间,那么最终所有的读取请求都会返回相同的值[1]。换句话说,不一致性是暂时的,最终会自行解决(假设网络中的任何故障最终都会被修复)。最终一致性的一个更好的名字可能是收敛的,因为我们预计所有的复制品最终会收敛到相同的值[2]。 +大多数复制的数据库至少提供了**最终一致性**,这意味着如果你停止向数据库写入数据并等待一段不确定的时间,那么最终所有的读取请求都会返回相同的值【1】。换句话说,不一致性是暂时的,最终会自行解决(假设网络中的任何故障最终都会被修复)。最终一致性的一个更好的名字可能是**收敛(convergence)**,因为我们预计所有的复本最终会收敛到相同的值【2】。 -然而,这是一个非常弱的保证 - 它没有说什么什么时候副本会汇合。在收敛之前,阅读可能会返回任何东西或没有东西[1]。例如,如果您编写了一个值,然后立即再次读取,则不能保证您将看到刚刚写入的值,因为可能会将读取路由到不同的副本(请参阅第152页的“读取自己的写入” )。 +然而,这是一个非常弱的保证——它并没有说什么什么时候副本会收敛。在收敛之前,读操作可能会返回任何东西或什么都没有【1】。例如,如果你写入了一个值,然后立即再次读取,这并不能保证你能看到刚跟写入的值,因为读请求可能会被路由到另外的副本上。(参阅“[读己之写](ch5.md#读己之写)” )。 -对于应用程序开发人员而言,最终的一致性是很难的,因为它与普通单线程程序中变量的行为有很大不同。如果将一个值赋给一个变量,然后很快读取,则不会期望读取旧值,或者读取失败。数据库表面上看起来像一个你可以读写的变量,但事实上它有更复杂的语义[3]。 +对于应用程序开发人员而言,最终一致性是很困难的,因为它与普通单线程程序中变量的行为有很大区别。如果将一个值赋给一个变量,然后很快地再次读取,你不会认为可能读到旧的值,或者读取失败。数据库表面上看起来像一个你可以读写的变量,但实际上它有更复杂的语义【3】。 -在处理只提供弱保证的数据库时,您需要不断地意识到它的局限性,而不是意外假设太多。错误往往是微妙的,很难找到测试,因为应用程序可能在大多数情况下运行良好。当系统出现故障(例如网络中断)或高并发时,最终一致性的边缘情况才变得明显。 +在与只提供弱保证的数据库打交道时,你需要始终意识到它的局限性,而不是意外地作出太多假设。错误往往是微妙的,很难找到,也很难测试,因为应用可能在大多数情况下运行良好。当系统出现故障(例如网络中断)或高并发时,最终一致性的边缘情况才会显现出来。 -在本章中,我们将探索数据系统可能选择提供的更强一致性模型。它们不是免费的:具有较强保证的系统可能会比保证较差的系统具有更差的性能或更少的容错性。尽管如此,更强有力的保证可以吸引人,因为它们更容易正确使用。一旦你看到了一些不同的一致性模型,你将能够更好地决定哪一个最适合你的需求。 +本章将探索数据系统可能选择提供的更强一致性模型。它不是免费的:具有较强保证的系统可能会比保证较差的系统具有更差的性能或更少的容错性。尽管如此,更强的保证可以吸引人,因为它们更容易用对。只有见过不同的一致性模型后,才能更好地决定哪一个最适合自己的需求。 -分布式一致性模型和我们之前讨论的事务隔离级别的层次结构有一些相似之处[4,5](参见“弱隔离级别”)。但是,虽然有一些重叠,但他们大多是独立的问题:事务隔离主要是为了避免由于同时执行事务而导致的竞争状态,而分布式一致性主要是在面对延迟和故障时协调副本的状态。 +**分布式一致性模型**和我们之前讨论的事务隔离级别的层次结构有一些相似之处【4,5】(参见“[弱隔离级别](ch7.md#弱隔离级别)”)。尽管两者有一部分内容重叠,但它们大多是无关的问题:事务隔离主要是为了,**避免由于同时执行事务而导致的竞争状态**,而分布式一致性主要关于,**面对延迟和故障时,如何协调副本间的状态。** -本章涵盖了广泛的话题,但我们将会看到,这些领域实际上是深深联系在一起的: +本章涵盖了广泛的话题,但我们将会看到这些领域实际上是紧密联系在一起的: + +* 首先看一下常用的**最强一致性模型**之一,**线性化(linearizability)**,并考察其优缺点。 +* 然后我们将检查分布式系统中[**事件顺序**](#顺序保证)的问题,特别是因果关系和全局顺序的问题。 +* 在第三部分(“[分布式事务和共识](#分布式事务和共识)”)中将探讨如何自动提交分布式事务,这将最终引导我们解决共识问题。 -* 我们首先看一下常用的最强一致性模型之一,线性化,并考察其优缺点。 -* 然后,我们将检查分布式系统中订购事件的问题(第339页的“订单保证”),特别是关于因果关系和总订购的问题。 -* 在第三部分(“分布式事务和共识”第359页)中,我们将探讨如何自动提交分布式事务,这将最终引导我们解决共识问题。 ## 线性化 +在**最终一致**的数据库,如果你在同一时刻问两个不同副本相同的问题,可能会得到两个不同的答案。这很让人困惑。如果数据库可以提供只有一个副本的假象(即,只有一个数据副本),那么事情就简单太多了。那么每个客户端都会有相同的数据视图,且不必担心复制滞后了。 +这就是**线性化(linearizability)**背后的想法【6】(也称为**原子一致性(atomic consistency)**【7】,**强一致性(strong consistency)**,**立即一致性(immediate consistency)**或**外部一致性(external consistency )**【8】)。线性化的精确定义相当微妙,我们将在本节的剩余部分探讨它。但是基本的想法是让一个系统看起来好像只有一个数据副本,而且所有的操作都是原子的。有了这个保证,即使实际中可能有多个副本,应用也不需要担心它们。 -在**最终一致**的数据库,如果你在同一时刻问两个不同副本相同的问题,可能会得到两个不同的答案。这很混乱。那岂不是简单了很多,如果数据库可以提供只有一个副本的幻象(即,只有一个数据副本),那么事情就简单太多了。那么每个客户端都会有相同的数据视图,而且您不必担心复制滞后。 - -这就是**线性化(linearizability)**背后的想法[6](也称为**原子一致性(atomic consistency)**[7],**强一致性(strong consistency)**,**立即一致性(immediate consistency)**或**外部一致性(external )**[8])。线性化的确切定义非常微妙,我们将在本节的其余部分探讨它。但是基本的想法是让一个系统看起来好像只有一个数据副本,而且所有的操作都是原子的。有了这个保证,即使现实中可能有多个副本,应用程序也不需要担心它们。 - -在一个线性化系统中,只要一个客户端成功完成写操作,所有客户端从数据库中读取数据必须能够看到刚刚写入的值。维护数据的单个副本的错觉是指低保读取的值是最近的,跟上时代的价值,而不是来自一个陈旧的缓存或副本。换句话说,线性化是一种新近的保证。为了澄清这个想法,我们来看看一个不可线性化系统的例子。 +在一个线性化系统中,只要一个客户端成功完成写操作,所有客户端从数据库中读取数据必须能够看到刚刚写入的值。维护数据的单个副本的错觉是指,系统能保障读到的值是最近的,最新的,不是来自一个陈旧的缓存或副本。换句话说,线性化是一个**新鲜度保证(recency guarantee)**。为了阐明这个想法,我们来看看一个不可线性化系统的例子。 ![](img/fig9-1.png) **图9-1 这个系统是非线性化的,导致球迷迷惑** -图9-1显示了一个非线性体育网站的例子[9]。爱丽丝和鲍勃正坐在同一个房间里,他们都在检查他们的手机,看看2014年FIFA世界杯决赛的结果。在最后得分公布后,爱丽丝刷新页面,看到获胜者宣布,并兴奋地告诉鲍勃。鲍勃无意中在自己的手机上重新加载,但他的请求转到了数据库副本上,而他的手机显示该游戏仍在进行中。 +[图9-1](img/fig9-1.png)展示了一个非线性化的,关于体育网站的例子【9】。Alice和Bob正坐在同一个房间里,都盯着各自的手机,关注着2014年FIFA世界杯决赛的结果。在最后得分公布后,Alice刷新页面,看到宣布了获胜者,并兴奋地告诉Bob。Bob难以置信地刷新了自己的手机,但他的请求路由到了一个落后的数据库副本上,手机显示比赛仍在进行。 -如果Alice和Bob在同一时间点击重新加载,如果他们获得了两个不同的查询结果,那么它们就不那么令人惊讶了,因为他们不知道服务器在何时处理它们各自的请求。然而,鲍勃知道他在听到爱丽丝惊呼最后的得分之后点击了重新加载按钮(启动了他的查询),因此他期望他的查询结果至少与爱丽丝一样近。他的查询返回陈旧结果的事实违反了线性化。 +如果Alice和Bob在同一时间刷新并获得了两个不同的查询结果,也许就没有那么令人惊讶了。因为他们不知道服务器处理他们请求的精确时刻。然而Bob是在听到Alice惊呼最后得分**之后**,点击了刷新按钮(启动了他的查询),因此他希望查询结果至少与爱丽丝一样新鲜。但他的查询返回了陈旧结果,这一事实违背了线性化的要求。 ### 什么使得系统线性一致? -线性化背后的基本思想很简单:使系统看起来好像只有一个数据副本。然而,确切地说,这意味着实际上需要一些小心实现。为了更好地理解线性化,让我们看看更多的例子。 +线性化背后的基本思想很简单:使系统看起来好像只有一个数据副本。然而确切来讲,实际上有更多要操心的地方。为了更好地理解线性化,让我们看看更多的例子。 -图9-2显示了三个客户端在可线性化数据库中同时读写相同的密钥x。在分布式系统文献中,x被称为注册实践,例如,它可以是关键值存储中的一个关键字,关系数据库中的一行或文档数据库中的一个文档。 +[图9-2](img/fig9-2.png)显示了三个客户端在线性化数据库中同时读写相同的键`x`。在分布式系统文献中,`x`被称为**寄存器(register)**,例如它可以是键值存储中的一个**键**,关系数据库中的一**行**或文档数据库中的一个**文档**。 ![](img/fig9-2.png) **图9-2 如果读取请求与写入请求并发,则可能会返回旧值或新值** -为了简单起见,图9-2仅显示了来自客户端的请求,而不是数据库的内部。每个小节都是由客户端发出的请求,其中小节的开始是发送请求的时间,小节的结尾是客户端收到响应的时间。由于可变的网络延迟,客户端不知道恰恰在数据库处理它的请求时——它只知道它在发送请求和接收响应的客户端之间的某个时间已经发生了。[^i] +为了简单起见,[图9-2](img/fig9-2.png)仅显示了来自客户端的请求,而不是数据库的内部。每个小节都是由客户端发出的请求,其中小节的开始是发送请求的时间,小节的结尾是客户端收到响应的时间。由于可变的网络延迟,客户端不知道恰恰在数据库处理它的请求时——它只知道它在发送请求和接收响应的客户端之间的某个时间已经发生了。[^i] -[^i]: 这个图的一个微妙的细节是它假定存在一个全局时钟,由水平轴表示。即使真实的系统通常没有准确的时钟(请参阅“不可靠的时钟”在本页287),但这种假设是可以的:为了分析分布式算法,我们可以假设一个精确的全局时钟存在因为该算法无法访问它[47]。相反,该算法只能看到由石英振荡器和NTP产生的实时逼近。 +[^i]: 这个图的一个微妙的细节是它假定存在一个全局时钟,由水平轴表示。即使真实的系统通常没有准确的时钟(请参阅“[不可靠的时钟](ch8.md#不可靠的时钟)”),但这种假设是允许的:为了分析分布式算法,我们可以假设一个精确的全局时钟存在,不过算法无法访问它【47】。算法只能看到由石英振荡器和NTP产生的实时逼近。 在这个例子中,寄存器有两种类型的操作: -* read(x)⇒v表示客户端请求读取寄存器x的值,数据库返回值v。 +* $ read(x)⇒v$表示客户端请求读取寄存器`x`的值,数据库返回值`v`。 -* write(x,v)⇒r表示客户端请求将寄存器x设置为值v,数据库返回响应r(这可能是好的或错误)。 +* $write(x,v)⇒r$表示客户端请求将寄存器`x`设置为值`v`,数据库返回响应`r`(可能正确,可能错误误)。 -在[图9-2]()中,x的值最初为0,客户端C执行写请求将其设置为1.发生这种情况时,客户端A和B反复轮询数据库以读取最新值。 A和B可能会为他们的阅读请求得到什么回应? +在[图9-2](img/fig9-2.png)中,x的值最初为0,客户端C执行写请求将其设置为1。发生这种情况时,客户端A和B反复轮询数据库以读取最新值。 A和B可能会为他们的阅读请求得到什么回应? * 客户端A的第一个读取操作在写入开始之前完成,因此必须返回旧值0。 * 客户端A的最后一次读操作是在写操作完成后开始的,所以如果数据库是线性化的,它必须定期返回新的值1:我们知道写操作必须在写操作开始和结束之间的某个时间被处理,并且读取操作必须在读取操作的开始和结束之间的某个时间进行处理。如果在写入结束后开始读取,则必须在写入之后处理读取,因此它必须看到写入的新值。 * 与写操作时间重叠的任何读操作可能会返回0或1,因为我们不知道写操作在处理读操作时是否生效。这些操作与写入同时发生。 -但是,这还不足以完全描述线性化:如果与写入同时发生的读取可以返回旧值或新值,那么读者可以看到数值在旧值和新值之间来回翻转几次写下去了。这不是我们所期望的仿真“单一数据副本”的系统。[^ii] +但是,这还不足以完全描述线性化:如果与写入同时发生的读取可以返回旧值或新值,那么读者可能会在写入期间看到数值在旧值和新值之间来回翻转。这不是我们所期望的仿真“单一数据副本”的系统。[^ii] -[^ii]: 一个寄存器中的读取可以返回旧值或新值,如果它们与写入同时发生,则称为常规寄存器[7,25] +[^ii]: 如果读取(与写入同时发生时)可能返回旧值或新值,则称该寄存器为**常规寄存器(regular register)**【7,25】 为了使系统可线性化,我们需要添加另一个约束,如**图9-3**所示 @@ -109,13 +108,13 @@ 在一个可线性化的系统中,我们可以想象,在x的值自动翻转从0到1的时候(在写操作的开始和结束之间)必定有一个时间点。因此,如果一个客户端的读取返回新的值1,即使写操作尚未完成,所有后续读取也必须返回新值。 -[图9-3]()中的箭头说明了这个时序依赖关系。客户端A是第一个读取新的值1的位置。在A的读取返回之后,B开始新的读取。由于B的读取严格在A的读取之后发生,因此即使C的写入仍在进行中,也必须返回1。 (与图9-1中的Alice和Bob的情况相同:在Alice读取新值之后,Bob也希望读取新的值。) +[图9-3](img/fig9-3.png)中的箭头说明了这个时序依赖关系。客户端A是第一个读取新的值1的位置。在A的读取返回之后,B开始新的读取。由于B的读取严格在A的读取之后发生,因此即使C的写入仍在进行中,也必须返回1。 (与[图9-1](img/fig9-1.png)中的Alice和Bob的情况相同:在Alice读取新值之后,Bob也希望读取新的值。) -我们可以进一步细化这个时序图,以可视化每个操作在某个时间点以原子方式生效。图9-4显示了一个更复杂的例子[10]。 +我们可以进一步细化这个时序图,以可视化每个操作在某个时间点以原子方式生效。[图9-4](img/fig9-4.png)显示了一个更复杂的例子【10】。 在[图9-4]()中,除了读写之外,还增加了第三种类型的操作: -* `cas(x,vold,vnew)`⇒r表示客户端请求进行原子比较与设置操作(请参阅“[比较并设置]()”一节)。如果寄存器x的当前值等于vold,则应该原子地设置为vnew。如果x≠vold,则操作应该保持寄存器不变并返回一个错误。 r是数据库的响应(正确或错误)。 +* $cas(x, v_{old}, v_{new})$⇒r表示客户端请求进行原子[**比较与设置**](ch7.md#比较并设置(CAS))操作。如果寄存器$x$的当前值等于$v_{old}$,则应该原子地设置为$v_{new}$。如果$x≠vold$,则操作应该保持寄存器不变并返回一个错误。 $r$是数据库的响应(正确或错误)。 [图9-4]()中的每个操作都在我们认为执行操作的时候用竖线标出(在每个操作的小节内部)。这些标记按顺序连接,结果必须是一个有效的寄存器读写序列(每次读取都必须返回最近一次写入设置的值)。 @@ -125,77 +124,79 @@ **图9-4 可视化读取和写入看起来已经生效的时间点。 B的最后读取不是可线性化的** -图9-4中有一些有趣的细节需要指出: +[图9-4]()中有一些有趣的细节需要指出: * 第一个客户端B发送一个读取x的请求,然后客户端D发送一个请求将x设置为0,然后客户端A发送请求将x设置为1.不过,返回到B的读取值为1(写入的值由A)。这是可以的:这意味着数据库首先处理D的写入,然后是A的写入,最后是B的读取。虽然这不是发送请求的顺序,但这是一个可以接受的顺序,因为这三个请求是并发的。也许B的读取请求在网络上略有延迟,所以在两次写入之后它只能到达数据库。 * 在客户端A从数据库收到响应之前,客户端B的读取返回1,表示写入值1已成功。这也是可以的:这并不意味着在写入之前读取了值,这只是意味着从数据库到客户端A的正确响应在网络中稍微延迟。 -* 此模型不承担任何事务隔离:另一个客户端可能随时更改值。例如,C首先读取1,然后读取2,因为两次读取之间的值由B更改。可以使用原子比较和设置(cas)操作来检查该值是否未被另一客户端同时更改:B和C的cas请求成功,但是D的cas请求失败(在数据库处理它时, x的值不再是0)。 +* 此模型不承担任何事务隔离:另一个客户端可能随时更改值。例如,C首先读取1,然后读取2,因为两次读取之间的值由B更改。可以使用原子**比较并设置(cas)**操作来检查该值是否未被另一客户端同时更改:B和C的cas请求成功,但是D的cas请求失败(在数据库处理它时, x的值不再是0)。 -* 客户B的最后读取(阴影栏中)不是线性化的。 该操作与C的cas写操作同时发生,它将x从2更新为4.在没有其他请求的情况下,B的读取返回2是可以的。然而,在B的读取开始之前,客户端A已经读取了新的值4 ,因此不允许B读取比A更旧的值。再次,与图9-1中的Alice和Bob的情况相同。 +* 客户B的最后读取(阴影栏中)不是线性化的。 该操作与C的cas写操作同时发生,它将x从2更新为4.在没有其他请求的情况下,B的读取返回2是可以的。然而,在B的读取开始之前,客户端A已经读取了新的值4 ,因此不允许B读取比A更旧的值。再次,与[图9-1](img/fig9-1.png)中的Alice和Bob的情况相同。 - 这就是线性化背后的直觉。 正式的定义[6]更准确地描述了它。 通过记录所有请求和响应的时序,并检查它们是否可以排列成有效的顺序,测试一个系统的行为是否可线性化是可能的(尽管在计算上是昂贵的)[11]。 + 这就是线性化背后的直觉。 正式的定义【6】更准确地描述了它。 通过记录所有请求和响应的时序,并检查它们是否可以排列成有效的顺序,测试一个系统的行为是否可线性化是可能的(尽管在计算上是昂贵的)【11】。 > ### 线性化与可序列化 > -> 线性化易于与可序列化性相混淆(请参见第251页上的“可序列化”),因为两个词似乎都是类似于“可以按顺序排列”的东西。但是,它们是两个完全不同的保证,区分他们: +> **线性化**容易和[**可序列化**](ch7.md#可序列化)相混淆,因为两个词似乎都是类似“可以按顺序排列”的东西。但它们是两种完全不同的保证,区分两者非常重要: > > ***可序列化*** > -> **可序列化(Serializability)**是事务的隔离属性,每个事务可以读写多个对象(行,文档,记录) - 请参阅第228页上的“单对象和多对象操作”。它确保事务的行为与如果他们已经按照一定的连续顺序执行(每个事务在下一个事务开始之前运行完成)。该顺序与事务实际执行的顺序不同[12]。 +> **可序列化(Serializability)**是事务的隔离属性,每个事务可以读写多个对象(行,文档,记录)——参阅“[单对象和多对象操作](ch7.md#单对象和多对象操作)”。它确保事务的行为与如果他们已经按照一定的连续顺序执行(每个事务在下一个事务开始之前运行完成)。该顺序与事务实际执行的顺序不同【12】。 > > ***线性化*** > -> **线性化(Linearizability)**是读取和写入寄存器(个别对象)的最新保证。它不会将操作组合到事务中,因此它不会阻止写入歪斜等问题(请参阅“写入歪斜和虚拟”),除非采取其他措施(如实现冲突)(请参阅本文的“实现冲突” 251)。 +> **线性化(Linearizability)**是读取和写入寄存器(单个对象)的**新鲜度保证**。它不会将操作组合到事务中,因此它不会阻止写偏差等问题(请参阅“[写偏差和幻读](ch7.md#写偏差和幻读)”),除非采取其他措施(例如[物化冲突](ch7.md#物化冲突))。 > -> 一个数据库可以提供可串行性和线性化,这种组合被称为严格的可串行性或强的单拷贝可串行性(strong-1SR)[4,13]。基于两阶段锁定的串行化实现(请参见“两阶段锁定(2PL)”一节,第257页)或实际的串行执行(请参见第242页的“实际的串行执行”)通常是可线性化的。 +> 一个数据库可以提供可串行性和线性化,这种组合被称为严格的可串行性或强的**单拷贝可串行性(strong-1SR)**【4,13】。基于两阶段锁定的串行化实现(请参见“[两阶段锁定(2PL)](#两阶段锁定(2PL))”一节)或**实际串行执行**(参见第“[实际串行执行](ch7.md#实际串行执行)”)通常是可线性化的。 > -> 但是,可序列化的快照隔离(请参见“可序列化的快照隔离(SSI)”第259页)不是线性化的:按照设计,它可以从一致的快照中进行读取,以避免锁定读者和写者之间的争用。一致性快照的要点在于,它不包括比快照更新的写入,因此从快照读取不是线性化的。 +> 但是,可序列化的快照隔离(请参见“[可序列化的快照隔离(SSI)](ch7.md#可序列化的快照隔离(SSI))”)不是线性化的:按照设计,它可以从一致的快照中进行读取,以避免锁定读者和写者之间的争用。一致性快照的要点在于,它不包括比快照更新的写入,因此从快照读取不是线性化的。 ### 依赖线性一致性 线性化在什么情况下有用?观看体育比赛的最后得分可能是一个轻率的例子:过了几秒钟的结果不可能在这种情况下造成任何真正的伤害。然而,线性化对于使系统正确工作的一个重要条件是有一些领域。 -锁定和领导选举 -一个使用单主复制的系统需要确保确实只有一个领导而不是几个(裂脑)。选择领导者的一种方法是使用一个锁:每个启动的节点试图获得锁,而成功的则成为领导者[14]。不管这个锁是如何实现的,它必须是可线性化的:所有节点必须同意哪个节点拥有锁;否则就没用了。 +#### 锁定和领导选举 -诸如Apache ZooKeeper [15]和etcd [16]之类的协调服务通常用于实现分布式锁和领导者选举。他们使用一致性算法以容错的方式实现可线性化的操作(我们在本章后面讨论这样的算法,在第364页的“容错共识”中)[^iii]。还有许多微妙的细节来正确地实现锁和领导者选择(例如,请参阅第301页上的“领导者和锁定”中的fencing问题),而像Apache Curator [17]这样的库则通过在ZooKeeper之上提供更高级别的配方来提供帮助。但是,线性化存储服务是这些协调任务的基础。 +一个使用单主复制的系统需要确保确实只有一个领导而不是几个(脑裂)。选择领导者的一种方法是使用一个锁:每个启动的节点试图获得锁,而成功的则成为领导者【14】。不管这个锁是如何实现的,它必须是可线性化的:所有节点必须同意哪个节点拥有锁;否则就没用了。 -[^iii]: 严格地说,ZooKeeper和etcd提供可线性化的写操作,但读取可能是陈旧的,因为默认情况下,它们可以由任何一个副本服务。您可以选择请求线性化读取:etcd调用这个法定读取[16],而在ZooKeeper中,您需要在读取[15]之前调用`sync()`。请参阅第350页上的“使用总订单广播实现线性存储”。 +诸如Apache ZooKeeper 【15】和etcd 【16】之类的协调服务通常用于实现分布式锁和领导者选举。他们使用一致性算法以容错的方式实现可线性化的操作(我们在本章后面讨论这样的算法,在“[容错共识](#容错共识)”中)[^iii]。还有许多微妙的细节来正确地实现锁和领导者选择(例如,请参阅第301页上的“[领导者和锁](#领导者和锁)”中的屏蔽问题),而像Apache Curator 【17】这样的库则通过在ZooKeeper之上提供更高级别的配方来提供帮助。但是,线性化存储服务是这些协调任务的基础。 -分布式锁定也在一些分布式数据库(如Oracle Real Application Clusters(RAC)[18])中以更细化的级别使用。 RAC对每个磁盘页面使用一个锁,多个节点共享对同一个磁盘存储系统的访问权限。由于这些可线性化的锁处于事务执行的关键路径上,RAC部署通常具有用于数据库节点之间通信的专用集群互连网络。 +[^iii]: 严格地说,ZooKeeper和etcd提供可线性化的写操作,但读取可能是陈旧的,因为默认情况下,它们可以由任何一个副本服务。您可以选择请求线性化读取:etcd调用这个法定读取【16】,而在ZooKeeper中,您需要在读取【15】之前调用`sync()`。请参阅第350页上的“[使用全局顺序广播实现线性存储](#)使用全局顺序广播实现线性存储”。 + +分布式锁定也在一些分布式数据库(如Oracle Real Application Clusters(RAC)【18】)中以更细化的级别使用。 RAC对每个磁盘页面使用一个锁,多个节点共享对同一个磁盘存储系统的访问权限。由于这些可线性化的锁处于事务执行的关键路径上,RAC部署通常具有用于数据库节点之间通信的专用集群互连网络。 #### 限制和唯一性保证 唯一性约束在数据库中很常见:例如,用户名或电子邮件地址必须唯一标识一个用户,而在文件存储服务中,不能有两个具有相同路径和文件名的文件。如果要在写入数据时强制执行此约束(例如,如果两个人试图同时创建一个具有相同名称的用户或文件,其中一个将返回一个错误),则需要线性化。 这种情况实际上类似于一个锁:当一个用户注册你的服务时,你可以想到他们获得了他们所选用户名的“锁定”。该操作也非常类似于原子比较和设置,将用户名设置为声明它的用户的ID,前提是用户名尚未被使用。 -如果你想要确保银行账户余额永远不会消极,或者你没有出售比仓库里的库存更多的物品,或者两个人不同时在同一个位置一个航班或一个剧院。这些约束条件都要求所有节点都同意一个最新的值(账户余额,库存水平,座位占用率)。 -在实际应用中,处理这些限制有时是可以接受的(例如,如果航班超额预订,您可以将客户转移到不同的航班并为其提供补偿)。在这种情况下,可能不需要线性化,我们将在第524页的“及时性和完整性”中讨论这种松散解释的约束。 +如果你想要确保银行账户余额永远不会为负数,或者你没有出售比仓库里的库存更多的物品,或者两个人不同时在同一个位置一个航班或一个剧院。这些约束条件都要求所有节点都同意一个最新的值(账户余额,库存水平,座位占用率)。 -然而,一个硬性的唯一性约束,比如你通常在关系数据库中发现的约束,需要线性化。其他类型的约束,如外键或属性约束,可以在不需要线性化的情况下实现[19]。 +在实际应用中,处理这些限制有时是可以接受的(例如,如果航班超额预订,您可以将客户转移到不同的航班并为其提供补偿)。在这种情况下,可能不需要线性化,我们将在第524页的“[及时性和完整性]()”中讨论这种松散解释的约束。 + +然而,一个硬性的唯一性约束,比如你通常在关系数据库中发现的约束,需要线性化。其他类型的约束,如外键或属性约束,可以在不需要线性化的情况下实现【19】。 #### 跨渠道的时间依赖性 -注意图9-1中的一个细节:如果Alice没有惊呼得分,Bob就不会知道他的查询结果是陈旧的。他会在几秒钟之后再次刷新页面,并最终看到最后的分数。由于系统中存在额外的通信信道(Alice对Bob的耳朵的声音),线性化破坏才被注意到。 +注意[图9-1](img/fig9-1.png)中的一个细节:如果Alice没有惊呼得分,Bob就不会知道他的查询结果是陈旧的。他会在几秒钟之后再次刷新页面,并最终看到最后的分数。由于系统中存在额外信道(Alice对Bob的耳朵的声音),线性化破坏才被注意到。 -计算机系统也会出现类似的情况。例如,假设您有一个用户可以上传照片的网站,而且后台进程会调整照片大小来降低分辨率,从而加快下载速度(缩略图)。该系统的体系结构和数据流如图9-5所示。 +计算机系统也会出现类似的情况。例如,假设您有一个用户可以上传照片的网站,而且后台进程会调整照片大小来降低分辨率,从而加快下载速度(缩略图)。该系统的体系结构和数据流如[图9-5](img/fig9-5.png)所示。 -需要明确指示图像大小调整器执行大小调整作业,并且通过消息队列将此指令从Web服务器发送到大小调整器(请参阅第11章)。 Web服务器不会将整个照片放在队列中,因为大多数消息中间件都是为小消息而设计的,而且照片的大小可能是几兆字节。相反,首先将照片写入文件存储服务,写入完成后,将调整器的指令放置在队列中。 +需要明确指示图像大小调整器执行大小调整作业,并且通过消息队列将此指令从Web服务器发送到大小调整器(请参阅[第11章](ch11.md))。 Web服务器不会将整个照片放在队列中,因为大多数消息中间件都是为小消息而设计的,而且照片的大小可能是几兆字节。相反,首先将照片写入文件存储服务,写入完成后,将调整器的指令放置在队列中。 ![](img/fig9-5.png) **图9-5 Web服务器和图像调整器通过文件存储和消息队列进行通信,打开竞争条件的可能性。** -如果文件存储服务是可线性化的,那么这个系统应该可以正常工作。如果它不是线性化的,则存在争用条件的风险:消息队列(图9-5中的步骤3和4)可能比存储服务内部的复制更快。在这种情况下,当调整器读取图像(步骤5)时,可能会看到图像的旧版本,或者什么都没有。如果它处理旧版本的图像,则文件存储中的全尺寸和调整大小的图像永久不一致。 +如果文件存储服务是可线性化的,那么这个系统应该可以正常工作。如果它不是线性化的,则存在争用条件的风险:消息队列([图9-5](img/fig9-5.png)中的步骤3和4)可能比存储服务内部的复制更快。在这种情况下,当调整器读取图像(步骤5)时,可能会看到图像的旧版本,或者什么都没有。如果它处理旧版本的图像,则文件存储中的全尺寸和调整大小的图像永久不一致。 -出现这个问题是因为Web服务器和调整器之间存在两个不同的通信通道:文件存储器和消息队列。没有线性化的新近性保证,这两个通道之间的竞争条件是可能的。这种情况类似于图9-1,两个通信渠道之间也存在竞争状态:数据库复制和爱丽丝口中与鲍勃耳朵之间的真实音频通道。 +出现这个问题是因为Web服务器和调整器之间存在两个不同的通信通道:文件存储器和消息队列。没有线性化的新近性保证,这两个通道之间的竞争条件是可能的。这种情况类似于[图9-1](img/fig9-1.png),两个通信渠道之间也存在竞争状态:数据库复制和Alice口中与Bob耳朵之间的真实音频通道。 -线性化并不是避免这种竞争条件的唯一方法,但它是最容易理解的。如果您控制附加的通信通道(例如在消息队列的情况下,而不是在Alice和Bob的情况下),则可以使用与我们在第162页的“读取自己的写入”额外的复杂性的成本。 +线性化并不是避免这种竞争条件的唯一方法,但它是最容易理解的。如果您控制附加的通信通道(例如在消息队列的情况下,而不是在Alice和Bob的情况下),则可以使用与我们在“[读己之写](ch5.md#读己之写)”额外的复杂性的成本。 ### 实现线性一致的系统 @@ -207,40 +208,40 @@ ***单主复制(可能可线性化)*** -在具有单引导程序复制功能的系统中(请参见“引导程序和追踪者”第152页),领导者具有用于写入的数据的主副本,而追随者在其他节点上保留数据的备份副本。如果你从领导读取数据,或者从同步更新的追随者读取数据,他们有可能是线性化的[^iv]。然而,并不是每个单独的领导者数据库都是可以线性化的,无论是通过设计(例如,因为它使用快照隔离)或者由于并发错误[10]。 +在具有单引导程序复制功能的系统中(请参见“[领导者与追随者](ch5.md#领导者与追随者)”),领导者具有用于写入的数据的主副本,而追随者在其他节点上保留数据的备份副本。如果你从领导读取数据,或者从同步更新的追随者读取数据,他们有可能是线性化的[^iv]。然而,并不是每个单独的领导者数据库都是可以线性化的,无论是通过设计(例如,因为它使用快照隔离)或者由于并发错误【10】。 -[^iv]: 对单领域数据库进行分区(分片),以便每个分区有一个单独的领导者,不会影响线性化,因为它只是单一对象的保证。 交叉分区事务是一个不同的问题(请参阅“分布式事务和共识”(第357页))。 +[^iv]: 对单领域数据库进行分区(分片),以便每个分区有一个单独的领导者,不会影响线性化,因为它只是单一对象的保证。 交叉分区事务是一个不同的问题(请参阅“[分布式事务和共识](#分布式事务和共识)”(第357页))。 -使用领导进行阅读依赖于你确定领导是谁的假设。正如在第300页的“真理被多数人定义”中所讨论的那样,一个节点很可能会认为它是领导者,而事实上并非如此 - 如果妄想的领导者继续为请求提供服务,可能违反线性化[20]。使用异步复制,故障转移甚至可能会丢失提交的写入(请参阅第156页的“处理节点中断”),这违反了耐久性和线性化。 +使用领导进行阅读依赖于你确定领导是谁的假设。正如在“[真理被多数人定义](ch8.md#真理被多数人定义)”中所讨论的那样,一个节点很可能会认为它是领导者,而事实上并非如此 - 如果妄想的领导者继续为请求提供服务,可能违反线性化【20】。使用异步复制,故障转移甚至可能会丢失提交的写入(参阅“[处理节点宕机](ch5.md#处理节点宕机)”),这违反了持久性和线性化。 ***共识算法(可线性化)*** -一些共识算法,我们将在本章后面讨论,与单引导者复制相似。然而,共识协议包含措施,以防止裂脑和陈旧的复制品。由于这些细节,协调算法可以安全地实现线性化存储。例如,Zoo-Keeper [21]和etcd [22]就是这样工作的。 +一些共识算法,我们将在本章后面讨论,与单引导者复制相似。然而,共识协议包含措施,以防止裂脑和陈旧的复制品。由于这些细节,协调算法可以安全地实现线性化存储。例如,Zookeeper 【21】和etcd 【22】就是这样工作的。 ***多主复制(不可线性化)*** -具有多引导程序复制的系统通常不是线性化的,因为它们同时在多个节点上处理写入,并将其异步复制到其他节点。由于这个原因,它们可能会产生冲突的写入,需要解析(请参阅第171页的“处理写入冲突”)。这种冲突是缺乏单一数据副本的人为因素。 +具有多引导程序复制的系统通常不是线性化的,因为它们同时在多个节点上处理写入,并将其异步复制到其他节点。由于这个原因,它们可能会产生冲突的写入,需要解析(请参阅第171页的“[处理写入冲突](ch5.md#处理写入冲突)”)。这种冲突是缺乏单一数据副本的人为因素。 ***无主复制(可能不是线性化的)*** -对于无领导者复制的系统(Dynamo风格;请参阅第177页的“无主复制”),有时候人们会声称通过要求法定读写(w + r> n)可以获得“强一致性”。根据法定人数的确切配置,取决于您如何界定强一致性,这是不正确的。 +对于无领导者复制的系统(Dynamo风格;参阅“[无主复制](ch5.md#无主复制)”),有时候人们会声称通过要求法定读写($w + r> n$)可以获得“强一致性”。根据法定人数的确切配置,取决于您如何界定强一致性,这是不正确的。 -基于时钟(例如,在Cassandra中;参见第291页上的“依赖于同步时钟”)的“最后写入胜利”冲突解决方法几乎是非线性的,因为时钟时间戳不能保证与时间戳一致由于时钟歪斜而导致的实际事件排序。不规范的法定人数(第183页的“马虎法定人数和暗示交接”)也破坏了线性化的可能性。即使是严格的法定人数,非线性行为也是可能的,如下一节所示。 +基于时钟(例如,在Cassandra中;参见第291页上的“[依赖于同步时钟](#依赖于同步时钟)”)的“最后写入胜利”冲突解决方法几乎是非线性的,因为时钟时间戳不能保证与时间戳一致由于时钟歪斜而导致的实际事件排序。不规范的法定人数(第183页的“[马虎法定人数和暗示交接](#马虎法定人数和暗示交接)”)也破坏了线性化的可能性。即使是严格的法定人数,非线性行为也是可能的,如下一节所示。 #### 线性化和法定人数 -直觉上,严格的仲裁读写应该是在Dynamo风格的模型中可线性化的。但是,当我们有可变的网络延迟时,就有可能存在竞争条件,如图9-6所示。 +直觉上,严格的仲裁读写应该是在Dynamo风格的模型中可线性化的。但是,当我们有可变的网络延迟时,就有可能存在竞争条件,如[图9-6](img/fig9-6.png)所示。 ![](img/fig9-6.png) **图9-6 尽管使用严格的法定人数,仍然是非线性的执行。** -在图9-6中,x的初始值为0,写入客户端通过向所有三个副本(n = 3,w = 3)发送写入将x更新为1。同时,客户端A从两个节点(r = 2)的仲裁中读取数据,并在其中一个节点上看到新值1。同时与写操作相关,客户端B从两个节点的不同仲裁中读取,并从两个节点中取回旧值0。 +在[图9-6](img/fig9-6.png)中,x的初始值为0,写入客户端通过向所有三个副本($n = 3, w = 3$)发送写入将x更新为1。同时,客户端A从两个节点($r = 2$)的仲裁中读取数据,并在其中一个节点上看到新值1。同时与写操作相关,客户端B从两个节点的不同仲裁中读取,并从两个节点中取回旧值0。 -仲裁条件满足(w + r> n),但是这个执行是不可排队的:B的请求在A的请求完成后开始,但是B返回旧值,而A返回新值。 (这又是爱丽丝和鲍勃的情况了[图9-1]()) +仲裁条件满足($w + r> n$),但是这个执行是不可排队的:B的请求在A的请求完成后开始,但是B返回旧值,而A返回新值。 (这又是爱丽丝和鲍勃的情况了[图9-1]()) -有趣的是,可以使Dynamo风格的定额以可降低的性能为代价线性化:读取器必须在将结果返回给应用程序之前,同步执行读取修复(请参阅“修复和反熵”一节第178页) ,并且作者必须在发送写入之前读取法定数量的最新状态[24,25]。然而,由于性能损失,Riak不执行同步读取修复[26]。 Cassandra确实等待读取修复以完成读取问题[27],但是如果由于使用了最后写入赢得冲突解决方案而导致同一个关键字有多个并发写入,则它将失去线性化。 +有趣的是,可以使Dynamo风格的定额以可降低的性能为代价线性化:读取器必须在将结果返回给应用程序之前,同步执行读取修复(请参阅“修复和反熵”一节第178页) ,并且作者必须在发送写入之前读取法定数量的最新状态【24,25】。然而,由于性能损失,Riak不执行同步读取修复【26】。 Cassandra确实等待读取修复以完成读取问题【27】,但是如果由于使用了最后写入赢得冲突解决方案而导致同一个关键字有多个并发写入,则它将失去线性化。 -而且,这种方式只能实现线性化的读写操作。线性化的比较和设置操作不能,因为它需要一个一致的算法[28]。 +而且这种方式只能实现线性化的读写操作。线性化的比较和设置操作不能,因为它需要一个一致的算法【28】。 总而言之,假设无Dynamo风格复制的无领导者系统不能提供线性化性是最安全的。 @@ -250,7 +251,7 @@ 由于一些复制方法可以提供线性化,其他复制方法则不能,因此更深入地探讨线性化的优缺点是很有趣的。 -我们已经在第五章讨论了不同复制方法的一些用例。例如,我们看到多领导者复制通常是多数据中心复制的理想选择(请参阅第165页上的“多数据中心操作”)。图9-7说明了这种部署的一个例子。 +我们已经在第五章讨论了不同复制方法的一些用例。例如,我们看到多领导者复制通常是多数据中心复制的理想选择(参阅“[多数据中心操作](ch5.md#多数据中心操作)”)。[图9-7](img/fig9-7.png)说明了这种部署的一个例子。 ![](img/fig9-7.png) @@ -272,51 +273,51 @@ * 如果您的应用程序需要线性化,并且由于网络问题某些副本与其他副本断开连接,则某些副本在断开连接时无法处理请求:它们必须等待,直到网络问题得到解决,或返回错误(无论哪种方式,他们变得不可用)。 * 如果您的应用程序不需要线性化,那么即使它与其他副本(如多引导程序)断开连接,也可以以每个副本可独立处理请求的方式进行写入。在这种情况下,应用程序可以在网络问题面前保持可用,但其行为不可线性化。 -[^v]: 这两种选择有时分别称为CP(在网络分区下一致但不可用)和AP(在网络分区下可用但不一致)。 但是,这种分类方案存在一些缺陷[9],所以最好避免。 +[^v]: 这两种选择有时分别称为CP(在网络分区下一致但不可用)和AP(在网络分区下可用但不一致)。 但是,这种分类方案存在一些缺陷【9】,所以最好避免。 -因此,不需要线性化的应用可以更容忍网络问题。这种见解通常被称为CAP定理[29,30,31,32],由Eric Brewer于2000年命名,尽管自20世纪70年代以来,分布式数据库的设计者已经知道了这种权衡[33,34,35,36 ]。 +因此,不需要线性化的应用可以更容忍网络问题。这种见解通常被称为CAP定理【29,30,31,32】,由Eric Brewer于2000年命名,尽管自20世纪70年代以来,分布式数据库的设计者已经知道了这种权衡【33,34,35,36】。 -CAP最初是作为一个经验法则提出的,没有准确的定义,目的是开始讨论数据库的权衡。当时,许多分布式数据库侧重于在具有共享存储的机器集群上提供可线性化的语义[18],并鼓励数据库工程师探索更广泛的分布式无共享系统的设计空间,这更适合于实施大规模的网络服务[37]。 CAP值得赞扬,因为这种文化转变 - 见证了自2000年代中期以来新的数据库技术的爆炸式增长(被称为NoSQL)。 +CAP最初是作为一个经验法则提出的,没有准确的定义,目的是开始讨论数据库的权衡。当时,许多分布式数据库侧重于在具有共享存储的机器集群上提供可线性化的语义【18】,并鼓励数据库工程师探索更广泛的分布式无共享系统的设计空间,这更适合于实施大规模的网络服务【37】。 CAP值得赞扬,因为这种文化转变——见证了自2000年代中期以来新的数据库技术的爆炸式增长(被称为NoSQL)。 > ### CAP定理没有帮助 > > CAP有时以这种面目出现:一致性,可用性和分区容忍:三者只能择其二。 > -> 个中只能选择从3中挑选出2个。不幸的是,这样做是误导的[32],因为网络分区是一种错误,所以它们不是你所拥有的一个选择:他们会发生,不管你喜欢还是不喜欢[38]。 +> 只能选择从3中挑选出2个。不幸的是,这样做是误导的【32】,因为网络分区是一种错误,所以它们不是你所拥有的一个选择:他们会发生,不管你喜欢还是不喜欢【38】。 > -> 在网络正常工作的时候,系统可以提供一致性(线性化)和总体可用性。发生网络故障时,您必须选择线性或总可用性。因此,一个更好的表达CAP的方法可以是一致的,或者在分区时可用[39]。一个更可靠的网络需要减少这个选择,但是在某些时候选择是不可避免的。 +> 在网络正常工作的时候,系统可以提供一致性(线性化)和总体可用性。发生网络故障时,您必须选择线性或总可用性。因此,一个更好的表达CAP的方法可以是一致的,或者在分区时可用【39】。一个更可靠的网络需要减少这个选择,但是在某些时候选择是不可避免的。 > -> 在CAP的讨论中,术语可用性有几个相互矛盾的定义,形式化作为一个定理[30]并不符合其通常的含义[40]。许多所谓的“高可用”(容错)系统实际上不符合CAP对可用性的特殊定义。总而言之,围绕着CAP有很多误解和困惑,并不能帮助我们更好地理解系统,所以最好避免使用CAP。 +> 在CAP的讨论中,术语可用性有几个相互矛盾的定义,形式化作为一个定理【30】并不符合其通常的含义【40】。许多所谓的“高可用”(容错)系统实际上不符合CAP对可用性的特殊定义。总而言之,围绕着CAP有很多误解和困惑,并不能帮助我们更好地理解系统,所以最好避免使用CAP。 -正式定义的CAP定理[30]的范围很窄,它只考虑一个一致性模型(即线性化)和一种故障(网络分区[^vi]或活动但彼此断开的节点)。它没有说任何有关网络延迟,死亡节点或其他权衡的事情。 因此,尽管CAP在历史上具有影响力,但对于设计系统来说,它没有实际价值[9,40]。 +正式定义的CAP定理【30】的范围很窄,它只考虑一个一致性模型(即线性化)和一种故障(网络分区[^vi]或活动但彼此断开的节点)。它没有说任何有关网络延迟,死亡节点或其他权衡的事情。 因此,尽管CAP在历史上具有影响力,但对于设计系统来说,它没有实际价值【9,40】。 -在分布式系统中有更多有趣的不可能的结果[41],并且CAP已经被更精确的结果所取代[2,42],所以它现在基本上是历史感兴趣的。 +在分布式系统中有更多有趣的不可能的结果【41】,并且CAP已经被更精确的结果所取代【2,42】,所以它现在基本上是历史感兴趣的。 [^vi]: 正如第279页的“实践中的网络故障”中所讨论的,本书使用分区来指将大数据集精细分解成小数据集(分片;参见第6章)。相比之下,网络分区是特定类型的网络故障,我们通常不会将其与其他类型的故障分开考虑。但是,由于是CAP的P,所以在这种情况下我们不能避免混淆。 #### 线性化和网络延迟 -虽然线性化是一个有用的保证,但实际上很少有系统实际上是线性化的。例如,现代多核CPU上的RAM甚至不可线性化[43]:如果一个CPU内核上运行的线程写入内存地址,而另一个CPU内核上的线程不久后读取相同的地址,保证读取第一个线程写入的值(除非使用了内存屏障或栅栏[44])。 +虽然线性化是一个有用的保证,但实际上很少有系统实际上是线性化的。例如,现代多核CPU上的RAM甚至不可线性化【43】:如果一个CPU内核上运行的线程写入内存地址,而另一个CPU内核上的线程不久后读取相同的地址,保证读取第一个线程写入的值(除非使用了内存屏障或栅栏【44】)。 -这种行为的原因是每个CPU内核都有自己的内存缓存和存储缓冲区。内存访问首先进入缓存默认情况下,任何更改异步写出到主内存。由于在缓存中访问数据比进入主内存要快[45],所以这个特性对于现代CPU的良好性能是至关重要的。但是,现在有几个数据副本(一个在主内存中,另外几个在不同的高速缓存中),而且这些副本是异步更新的,因此线性化会丢失。 +这种行为的原因是每个CPU内核都有自己的内存缓存和存储缓冲区。内存访问首先进入缓存默认情况下,任何更改异步写出到主内存。由于在缓存中访问数据比进入主内存要快【45】,所以这个特性对于现代CPU的良好性能是至关重要的。但是,现在有几个数据副本(一个在主内存中,另外几个在不同的高速缓存中),而且这些副本是异步更新的,因此线性化会丢失。 为什么要做这个交换?使用CAP定理来证明多核内存一致性模型是没有意义的:在一台计算机中,我们通常假定可靠的通信,并且我们不希望一个CPU内核能够继续正常的操作与电脑的其他部分断开连接。降低线性化的原因是性能,而不是容错。 -许多分布式数据库也是如此,它们选择不提供线性保证:它们主要是为了提高性能,而不是为了容错[46]。线性化速度很慢 - 这一直是事实,不仅在网络故障期间。 +许多分布式数据库也是如此,它们选择不提供线性保证:它们主要是为了提高性能,而不是为了容错【46】。线性化速度很慢 - 这一直是事实,不仅在网络故障期间。 -我们不能找到一个更有效的线性化存储实现吗?看来答案是否定的:Attiya和Welch [47]证明,如果你想要线性化,读写请求的响应时间至少与网络延迟的不确定性成正比。在像大多数计算机网络一样具有高度可变延迟的网络中(请参见“超时和无限延迟”(第267页)),可线性读写的响应时间不可避免地会很高。线性化算法不存在,但是一致性较弱的模型可以更快,所以这种权衡对于延迟敏感的系统是很重要的。在第12章中,我们将讨论一些避免线性化而不牺牲正确性的方法。 +我们不能找到一个更有效的线性化存储实现吗?看来答案是否定的:Attiya和Welch 【47】证明,如果你想要线性化,读写请求的响应时间至少与网络延迟的不确定性成正比。在像大多数计算机网络一样具有高度可变延迟的网络中(请参见“[超时和无限延迟](ch8.md#超时和无限延迟)”(第267页)),可线性读写的响应时间不可避免地会很高。线性化算法不存在,但是一致性较弱的模型可以更快,所以这种权衡对于延迟敏感的系统是很重要的。在第12章中,我们将讨论一些避免线性化而不牺牲正确性的方法。 ## 顺序保证 -我们之前曾经说过,线性化寄存器的行为就好像只有一个数据拷贝一样,而且每一个操作在某个时间点似乎都是原子地生效的。这个定义意味着操作按照一定的顺序执行。我们通过按照它们似乎已经执行的顺序加入操作来说明图9-4中的顺序。 +我们之前曾经说过,线性化寄存器的行为就好像只有一个数据拷贝一样,而且每一个操作在某个时间点似乎都是原子地生效的。这个定义意味着操作按照一定的顺序执行。我们通过按照它们似乎已经执行的顺序加入操作来说明[图9-4]()中的顺序。 订购在本书中一直是反复出现的主题,这表明这可能是一个重要的基本概念。让我们简要回顾一下我们在其中讨论过的其他一些情况: -* 在第5章中,我们看到领导者在单引导者复制中的主要目的是确定复制日志中的写入顺序 - 也就是追随者应用这些写入的顺序。如果不存在单个领导,则可能由于并发操作而发生冲突(请参阅第171页的“处理写冲突”)。 -* 我们在第7章中讨论的可序列化是关于确保事务按照某种顺序执行的行为。它可以通过以该序列字面执行事务来实现,或者通过允许并行执行,同时防止序列化冲突(通过锁定或中止)来实现。 -* 我们在第8章讨论过的在分布式系统中使用时间戳和时钟(请参阅第291页上的“依赖于同步时钟”)是另一种将秩序引入无序世界的尝试,例如确定两个写入中的哪一个稍后发生。 +* 在[第5章](ch5.md)中,我们看到领导者在单引导者复制中的主要目的是确定复制日志中的写入顺序——也就是追随者应用这些写入的顺序。如果不存在单个领导,则可能由于并发操作而发生冲突(参阅“[处理写入冲突](ch5.md#处理写入冲突)”)。 +* 我们在[第7章](ch7.md)中讨论的可序列化是关于确保事务按照某种顺序执行的行为。它可以通过以该序列字面执行事务来实现,或者通过允许并行执行,同时防止序列化冲突(通过锁定或中止)来实现。 +* 我们在[第8章](ch8.md)讨论过的在分布式系统中使用时间戳和时钟(参阅“[依赖于同步时钟](ch8.md#依赖于同步时钟)”)是另一种将顺序引入无序世界的尝试,例如确定两个写入中的哪一个稍后发生。 事实证明,排序,线性化和共识之间有着深刻的联系。尽管这个概念比本书的其他部分更具理论性和抽象性,但对于澄清我们对什么是系统可以做什么和不可以做什么而言是非常有帮助的。我们将在接下来的几节中探讨这个话题。 @@ -324,14 +325,15 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 订单不断涌现有几个原因,其中一个原因是它有助于保持因果关系。在这本书的过程中,我们已经看到了几个例子,其中因果关系是重要的: -* 在“[一致前缀读取]()”(图5-5)中,我们看到一个例子,一个对话的观察者首先看到问题的答案,然后回答问题。这是令人困惑的,因为它违背了我们对因果的直觉:如果一个问题得到了回答,那么显然这个问题必须首先在那里,因为给出答案的人必须看到这个问题(假设他们不是精神的,未来)。我们说在问题和答案之间存在因果关系。 -* 图5-9中出现了类似的模式,我们在这里看到三位领导者之间的复制,并注意到由于网络延迟,一些文字可能会“超过”其他文字。从其中一个副本的角度看,好像有一个不存在的行的更新。这里的因果意味着一行必须先被创建,然后才能被更新。 -* 在第184页的“检测并发写入”中,我们观察到如果您有两个操作A和B,则有三种可能性:A发生在B之前,或B发生在A之前,或者A和B并发。这是在关系是因果关系的另一种表达之前发生的:如果A发生在B之前,那么意味着B可能已经知道了A,或者建立在A上,或者依赖于A.如果A和B是并发的,那么他们;换句话说,我们确信没有人知道另一个。 -* 在事务快照隔离的上下文中(“快照隔离和可重复读”(第223页)),我们说事务从一致的快照中读取。但在这方面“一致”是什么意思?这意味着与因果关系一致:如果快照包含答案,它也必须包含被回答的问题[48]。在一个时间点观察整个数据库使其与因果性保持一致:在那个时间点之前发生的所有操作的效果都是可见的,但是没有发生严重的后续操作。读取偏斜(非重复读取,如图7-6所示)意味着读取的数据处于违反因果关系的状态。 -* 我们在事务之间编写歪斜的示例(请参见第249页上的“编写偏见和疑惑”)也说明了因果关系:在图7-8中,Alice被允许关闭电话,因为交易认为Bob仍在通话,反之亦然。在这种情况下,去电的动作因果关系取决于观察当前谁在呼叫。可序列化的快照隔离(请参见“可序列化的快照隔离(SSI)”(第267页))通过跟踪事务之间的因果依赖关系来检测写入歪斜。 -* 在爱丽丝和鲍勃看足球的例子中(图9-1),在听到爱丽丝惊呼结果之后,鲍勃从服务器得到一个陈旧结果的事实是一个因果关系的违反:爱丽丝的感叹是因果关系依赖于比分,所以鲍勃应该也可以在听完艾丽斯后看到比分。在图像大小调整服务的幌子下,第331页的“跨渠道时序依赖关系”中再次出现了相同的模式。 +* 在“[一致前缀读取]()”([图5-5](img/fig5-5.png))中,我们看到一个例子,一个对话的观察者首先看到问题的答案,然后回答问题。这是令人困惑的,因为它违背了我们对因果的直觉:如果一个问题得到了回答,那么显然这个问题必须首先在那里,因为给出答案的人必须看到这个问题(假设他们不是精神的,未来)。我们说在问题和答案之间存在因果关系。 +* [图5-9](img/fig5-9.png)中出现了类似的模式,我们在这里看到三位领导者之间的复制,并注意到由于网络延迟,一些文字可能会“超过”其他文字。从其中一个副本的角度看,好像有一个不存在的行的更新。这里的因果意味着一行必须先被创建,然后才能被更新。 +* 在“[检测并发写入](ch5.md#检测并发写入)”中,我们观察到如果您有两个操作A和B,则有三种可能性:A发生在B之前,或B发生在A之前,或者A和B并发。这是在关系是因果关系的另一种表达之前发生的:如果A发生在B之前,那么意味着B可能已经知道了A,或者建立在A上,或者依赖于A.如果A和B是并发的,那么他们;换句话说,我们确信没有人知道另一个。 +* 在事务快照隔离的上下文中(“[快照隔离和可重复读](ch7.md#快照隔离和可重复读)”),我们说事务从一致的快照中读取。但在这方面“一致”是什么意思?这意味着与因果关系一致:如果快照包含答案,它也必须包含被回答的问题【48】。在一个时间点观察整个数据库使其与因果性保持一致:在那个时间点之前发生的所有操作的效果都是可见的,但是没有发生严重的后续操作。读取偏斜(非重复读取,如[图7-6](img/fig7-6.png)所示)意味着读取的数据处于违反因果关系的状态。 +* 我们在事务之间写偏差的示例(参见“[写偏差和幻象](ch7.md#写偏差和幻象)”)也说明了因果关系:在[图7-8](img/fig7-8.png)中,Alice被允许关闭电话,因为交易认为Bob仍在通话,反之亦然。在这种情况下,去电的动作因果关系取决于观察当前谁在呼叫。[可序列化的快照隔离](ch7.md#可序列化的快照隔离(SSI))通过跟踪事务之间的因果依赖关系来检测写入歪斜。 +* 在爱丽丝和鲍勃看足球的例子中([图9-1](img/fig9-1.png)),在听到爱丽丝惊呼结果之后,鲍勃从服务器得到一个陈旧结果的事实是一个因果关系的违反:爱丽丝的感叹是因果关系依赖于比分,所以鲍勃应该也可以在听完艾丽斯后看到比分。在图像大小调整服务的幌子下,第331页的“[跨渠道时序依赖关系](#跨渠道时序依赖关系)”中再次出现了相同的模式。 因果关系对事件施加了一种排序:在收到该消息之前发送消息;问题出现在答案之前。而且,就像现实生活中一样,有一件事情会导致另一件事情:一个节点读取一些数据,然后写出一些结果,另一个节点读取写入的内容并依次写入其他内容,等等。这些依赖因果关系的操作链定义了系统中的因果顺序,即在什么之前发生了什么。 + 如果一个系统服从因果关系所规定的顺序,我们说它是因果关系一致的。例如,快照隔离提供了因果一致性:当您从数据库中读取数据,并且看到一些数据时,您还必须能够看到任何因果关系的数据(假设在此期间还没有被删除)。 @@ -340,17 +342,17 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 **全序关系(total order)**允许任何两个元素进行比较,所以如果你有两个元素,你总是可以说哪个更大,哪个更小。例如,自然数是完全有序的:如果我给你两个数字,比如说5和13,那么你可以告诉我,13大于5。 -但是,数学集并不完全排序:是{a,b}大于{b,c}?那么,你不能真正地比较它们,因为它们都不是其中的一个子集。我们说它们是无法比拟的,因此数学集是部分排序的:在某些情况下,一个集大于另一个(如果一个集包含另一个集的所有元素),但在其他情况下它们是无法比拟的。 +但是,数学集并不完全排序:是`{a, b}`大于`{b, c}`?那么,你不能真正地比较它们,因为它们都不是其中的一个子集。我们说它们是无法比拟的,因此数学集是部分排序的:在某些情况下,一个集大于另一个(如果一个集包含另一个集的所有元素),但在其他情况下它们是无法比拟的。 总订单和部分订单之间的差异反映在不同的数据库一致性模型中: ***线性化*** -在一个可线性化的系统中,我们有一个总的操作顺序:如果系统的行为就好像只有一个数据副本,并且每个操作都是原子的,这意味着对于任何两个操作,我们总是可以说哪个操作先发生。这个总的排序在图9-4中以时间线表示。 +在一个可线性化的系统中,我们有一个总的操作顺序:如果系统的行为就好像只有一个数据副本,并且每个操作都是原子的,这意味着对于任何两个操作,我们总是可以说哪个操作先发生。这个总的排序在[图9-4](img/fig9-4.png)中以时间线表示。 ***因果关系*** -我们说过,如果两个操作都没有发生在另一个之前,那么这两个操作是并发的(请参阅第186页上的“发生之前的关系和并发”)。换句话说,如果两个事件是因果关系的(一个发生在另一个事件之前),则它们被排序,但是如果它们是并发的,则它们是无法比拟的。这意味着因果关系定义了一个部分的秩序,而不是一个整体的秩序:一些行动是相互排序的,但有些是无法比拟的。 +我们说过,如果两个操作都没有发生在另一个之前,那么这两个操作是并发的(请参阅第186页上的“[发生之前的关系和并发]()”)。换句话说,如果两个事件是因果关系的(一个发生在另一个事件之前),则它们被排序,但是如果它们是并发的,则它们是无法比拟的。这意味着因果关系定义了一个部分的秩序,而不是一个整体的秩序:一些行动是相互排序的,但有些是无法比拟的。 因此,根据这个定义,在可数据化数据存储中不存在并发操作:必须有一个时间线,所有的操作都是按顺序排列的。可能有几个请求等待处理,但是数据存储确保了每个请求都是在单个时间点自动处理的,并且在单个时间轴上作用于单个数据副本,而没有任何并发性。 @@ -360,14 +362,14 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 #### 线性化强于因果一致性 -那么因果顺序和线性化之间的关系是什么?答案是线性化意味着因果关系:任何可线性化的系统都能正确保存注意力[7]。特别是,如果系统中有多个通信通道(如图9-5中的消息队列和文件存储服务),线性可确保因果关系被自动保留,而系统不必做任何特殊的事情(如通过不同部件之间的时间戳)。 +那么因果顺序和线性化之间的关系是什么?答案是线性化意味着因果关系:任何可线性化的系统都能正确保存注意力【7】。特别是,如果系统中有多个通信通道(如图9-5中的消息队列和文件存储服务),线性可确保因果关系被自动保留,而系统不必做任何特殊的事情(如通过不同部件之间的时间戳)。 线性化确保因果关系的事实使线性化系统变得简单易懂,更具吸引力。然而,正如第335页的“线性可用性的成本”中所讨论的,使系统可线性化可能会损害其性能和可用性,尤其是在系统具有严重的网络延迟的情况下(例如,如果地理位置分散的话)。出于这个原因,一些分布式数据系统已经放弃了线性化,这使得它们可以获得更好的性能,但却使它们难以工作。 -好消息是中间地带是可能的。线性化不是保持因果关系的唯一途径 - 还有其他方法。一个系统可以在原因上是一致的,不会造成使其线性化的性能命中(特别是CAP定理不适用)。事实上,因果一致性是最强可能的一致性模型,不会由于网络延迟而减慢,并且在网络故障时仍然可用[2,42]。 +好消息是中间地带是可能的。线性化不是保持因果关系的唯一途径 - 还有其他方法。一个系统可以在原因上是一致的,不会造成使其线性化的性能命中(特别是CAP定理不适用)。事实上,因果一致性是最强可能的一致性模型,不会由于网络延迟而减慢,并且在网络故障时仍然可用【2,42】。 -在许多情况下,似乎需要线性化的系统实际上只需要确定因果一致性,这可以更有效地实施。基于这种观察,研究人员正在探索新的数据库来保存因果关系,其性能和可用性特征与最终一致的系统类似[49,50,51]。 -由于这项研究是相当新的,其中没有很多已经进入生产系统,仍然有挑战需要克服[52,53]。但是,这是未来系统的一个有利的方向。 +在许多情况下,似乎需要线性化的系统实际上只需要确定因果一致性,这可以更有效地实施。基于这种观察,研究人员正在探索新的数据库来保存因果关系,其性能和可用性特征与最终一致的系统类似【49,50,51】。 +由于这项研究是相当新的,其中没有很多已经进入生产系统,仍然有挑战需要克服【52,53】。但是,这是未来系统的一个有利的方向。 #### 捕获因果关系 @@ -375,7 +377,7 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 为了确定因果依赖关系,我们需要一些方法来描述系统中节点的“知识”。如果节点在发出写入Y时已经看到X值,则X和Y可能是因果关系的。这个分析使用了你在欺诈指控的刑事调查中所期望的那些问题:CEO在做出决定时是否知道X? -在其他操作之前确定哪些操作发生的技术与我们在第181页中的“检测并发写入”中所讨论的内容类似。该节讨论无领导者数据存储区中的因果关系,我们需要检测到同一个关键字为了防止丢失更新。因果关系更进一步:它需要跟踪整个数据库的因果关系,而不仅仅是一个关键。版本向量可以被推广到做这个[54]。 +在其他操作之前确定哪些操作发生的技术与我们在第181页中的“检测并发写入”中所讨论的内容类似。该节讨论无领导者数据存储区中的因果关系,我们需要检测到同一个关键字为了防止丢失更新。因果关系更进一步:它需要跟踪整个数据库的因果关系,而不仅仅是一个关键。版本向量可以被推广到做这个【54】。 为了确定因果顺序,数据库需要知道应用程序读取哪个版本的数据。这就是为什么在图5-13中,来自先前操作的版本号在写入时被传回到数据库的原因。在SSI的冲突检测中会出现类似的想法,如“[可序列化的快照隔离(SSI)]()”中所述:当事务要提交时,数据库将检查它读取的数据版本是否仍然运行至今。为此,数据库跟踪哪个数据已经被哪个事务读取。 @@ -385,7 +387,7 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 虽然因果关系是一个重要的理论概念,但实际上跟踪所有的因果关系是不切实际的。在许多应用程序中,客户端在写入内容之前会先读取大量数据,然后不清楚写入是因果关系依赖于全部还是仅仅一些先前的读取。显式跟踪所有已读取的数据将意味着很大的开销。 -但是,还有一个更好的方法:我们可以使用序列号或时间戳来排序事件。时间戳不一定来自时钟(或物理时钟,有很多问题,如“不可靠时钟”在287页中所述)。它可以来自一个逻辑时钟,这是一个算法来产生一个数字序列来识别操作,通常使用计数器,每个操作增加计数器。 +但是,还有一个更好的方法:我们可以使用序列号或时间戳来排序事件。时间戳不一定来自时钟(或物理时钟,有很多问题,如“[不可靠时钟](ch8.md#不可靠的时钟)”)。它可以来自一个逻辑时钟,这是一个算法来产生一个数字序列来识别操作,通常使用计数器,每个操作增加计数器。 这样的序列号或时间戳是紧凑的(只有几个字节大小),它们提供了一个总的顺序:也就是说,每一个操作都有一个唯一的序列号,你总是可以比较两个序列号来确定哪个更大(即,哪些操作发生在后面)。 @@ -393,14 +395,14 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 [^vii]: 与因果关系不一致的整个订单很容易创建,但不是很有用。例如,您可以为每个操作生成随机UUID,并按照字典顺序比较UUID以定义操作的总顺序。这是一个有效的总顺序,但是随机的UUID并不告诉你哪个操作首先实际发生,或者操作是否是并发的。 -在具有单引导程序复制的数据库中(请参见“引导程序和追踪者”(第152页)),复制日志定义了与因果关系一致的写操作总顺序。领导者可以简单地为每个操作增加一个计数器,从而为复制日志中的每个操作分配一个单调递增的序列号。如果一个追随者按照他们在复制日志中出现的顺序来应用写入,那么追随者的状态始终是因果一致的(即使它落后于领导者)。 +在具有单引导程序复制的数据库中(请参见“[领导者与追随者](ch5.md#领导者与追随者)”),复制日志定义了与因果关系一致的写操作总顺序。领导者可以简单地为每个操作增加一个计数器,从而为复制日志中的每个操作分配一个单调递增的序列号。如果一个追随者按照他们在复制日志中出现的顺序来应用写入,那么追随者的状态始终是因果一致的(即使它落后于领导者)。 #### 非因果序列号发生器 如果没有一个领导者(可能是因为您使用的是多领导者或无领导者的数据库,或者是因为数据库是分区的),那么如何为操作生成序列号还不太清楚。实践中使用了各种方法: * 每个节点都可以生成自己独立的一组序列号。例如,如果有两个节点,一个节点只能生成奇数,而另一个节点只能生成偶数。通常,可以在序列号的二进制表示中保留一些位以包含唯一的节点标识符,这将确保两个不同的节点永远不会生成相同的序列号。 -* 您可以将时间戳从时钟(物理时钟)附加到每个操作[55]。这样的时间戳是不连续的,但是如果它们具有足够高的分辨率,那么它们可能足以完成命令操作。这个事实用于最后的写赢取冲突解决方法(请参阅第291页的“订购事件的时间戳”)。 +* 您可以将时间戳从时钟(物理时钟)附加到每个操作【55】。这样的时间戳是不连续的,但是如果它们具有足够高的分辨率,那么它们可能足以完成命令操作。这个事实用于最后的写赢取冲突解决方法(请参阅第291页的“订购事件的时间戳”)。 * 您可以预先分配序列号的块。例如,节点A可能要求从1到1,000的序列号的块,并且节点B可能要求该区块从1,001到2,000。然后,每个节点可以独立分配其块的序列号,并在序列号的提供开始变低时分配一个新的块。 这三个选项都比单独的领导者增加一个计数器的表现更好,并且更具可扩展性。它们为每个操作生成一个唯一的,大约增加的序列号。然而,他们都有一个问题:他们产生的序列号与因果关系不一致。 @@ -419,9 +421,9 @@ CAP最初是作为一个经验法则提出的,没有准确的定义,目的 #### Lamport时间戳 -尽管刚才描述的三个序列号发生器与因果关系不一致,但实际上有一个简单的方法来产生与因果关系一致的序列号。它被称为Lamport时间戳,莱斯利·兰波特(Leslie Lamport)于1978年提出[56],现在是分布式系统领域中被引用最多的论文之一。 +尽管刚才描述的三个序列号发生器与因果关系不一致,但实际上有一个简单的方法来产生与因果关系一致的序列号。它被称为Lamport时间戳,莱斯利·兰波特(Leslie Lamport)于1978年提出【56】,现在是分布式系统领域中被引用最多的论文之一。 -图9-8说明了Lamport时间戳的使用。每个节点都有一个唯一的标识符,每个节点都保存一个处理操作数量的计数器。 Lamport时间戳然后是一对(计数器,节点ID)。二节点有时可能具有相同的计数器值,但通过在时间戳中包含节点ID,每个时间戳都是唯一的。 +[图9-8](img/fig9-8.png)说明了Lamport时间戳的使用。每个节点都有一个唯一的标识符,每个节点都保存一个处理操作数量的计数器。 Lamport时间戳然后是一对(计数器,节点ID)。二节点有时可能具有相同的计数器值,但通过在时间戳中包含节点ID,每个时间戳都是唯一的。 ![](img/fig9-8.png) @@ -441,13 +443,13 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 #### 光有时间戳排序还不够 虽然Lamport时间戳定义了与因果关系一致的操作总顺序,但它们还不足以解决分布式系统中的许多常见问题。 -例如,考虑一个需要确保用户名唯一标识用户帐户的系统。如果两个用户同时尝试使用相同的用户名创建帐户,则其中一个应该成功,另一个应该失败。 (我们之前在第301页的“领导和锁定”中提到过这个问题。) +例如,考虑一个需要确保用户名唯一标识用户帐户的系统。如果两个用户同时尝试使用相同的用户名创建帐户,则其中一个应该成功,另一个应该失败。 (我们之前在第301页的“[领导和锁定](#领导和锁定)”中提到过这个问题。) 乍看之下,似乎总的操作顺序(例如,使用Lamport时间戳)应该足以解决此问题:如果创建了两个具有相同用户名的帐户,请选择时间戳较低的那个作为获胜者(一个谁先抓住用户名),并让更大的时间戳失败。由于时间戳是完全有序的,所以这个比较总是有效的。 这种方法适用于事后确定胜利者:一旦收集了系统中的所有用户名创建操作,就可以比较他们的时间戳。然而,当一个节点刚刚收到用户的一个请求来创建一个用户名,并且现在需要决定这个请求是成功还是失败,这是不够的。此时,节点不知道另一个节点是否正在同时创建具有相同用户名的帐户,以及其他节点可以分配给该操作的时间戳。 -为了确保没有其他节点正在使用相同的用户名和较低的时间戳同时创建一个帐户,您必须检查每个节点,看看它在做什么[56]。如果其中一个节点由于网络问题而出现故障或无法到达,则该系统将停止工作。这不是我们需要的那种容错系统。 +为了确保没有其他节点正在使用相同的用户名和较低的时间戳同时创建一个帐户,您必须检查每个节点,看看它在做什么【56】。如果其中一个节点由于网络问题而出现故障或无法到达,则该系统将停止工作。这不是我们需要的那种容错系统。 这里的问题是,只有在收集了所有的操作之后,操作的总顺序才会出现。如果另一个节点已经产生了一些操作,但是你还不知道它们是什么,那么就不能构造最终的操作顺序:来自另一个节点的未知操作可能需要被插入到总数的不同位置订购。 @@ -459,13 +461,13 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 如果你的程序只运行在一个CPU内核上,那么定义一个操作总的顺序是很容易的:它只是CPU执行的顺序。但是,在分布式系统中,让所有节点在相同的操作顺序上达成一致是非常棘手的。在最后一节中,我们讨论了按时间戳或序列号进行排序,但发现它不如单主复制(如果使用时间戳排序来实现唯一性约束,则不能容忍任何错误)。 -如前所述,单引导程序复制通过选择一个节点作为引导程序来确定操作的总顺序,并对引导程序上的单个CPU核心上的所有操作进行排序。接下来的挑战是如果吞吐量大于单个领导者可以处理的情况下如何扩展系统,以及如果领导者失败(参见第156页的“处理节点中断”),如何处理故障转移。在分布式系统文献中,这个问题被称为全序广播或原子广播[^ix]【25,57,58】。 +如前所述,单引导程序复制通过选择一个节点作为引导程序来确定操作的总顺序,并对引导程序上的单个CPU核心上的所有操作进行排序。接下来的挑战是如果吞吐量大于单个领导者可以处理的情况下如何扩展系统,以及如果领导者失败(参见第156页的“[处理节点宕机](#处理节点宕机)”),如何处理故障转移。在分布式系统文献中,这个问题被称为全序广播或原子广播[^ix]【25,57,58】。 [^ix]: “原子广播”这个术语是传统的,但是它是非常混乱的,因为它与原子的其他用法不一致:它与ACID事务中的原子性没有任何关系,只是与原子操作(在多线程编程的意义上 )或原子寄存器(线性化存储)。 总的订单组播是另一个同义词。 > #### 顺序保证的范围 > -> 每个分区有一个单独的引导程序的分区数据库通常只对每个分区进行排序,这意味着它们不能提供跨分区的一致性保证(例如,一致的快照,外键引用)。 所有分区的总排序是可能的,但需要额外的协调[59]。 +> 每个分区有一个单独的引导程序的分区数据库通常只对每个分区进行排序,这意味着它们不能提供跨分区的一致性保证(例如,一致的快照,外键引用)。 所有分区的总排序是可能的,但需要额外的协调【59】。 总订单广播通常被描述为在节点之间交换消息的协议。 非正式地,它要求总是满足两个安全属性: @@ -483,20 +485,20 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 像ZooKeeper和etcd这样的共识服务实际上是实现全面的订单播放。这个事实暗示了整个命令广播和共识之间有着密切的联系,我们将在本章后面进行探讨。 -总订单广播正是您所需的数据库复制:如果每封邮件都表示写入数据库,并且每个副本按相同的顺序处理相同的写入,则副本将保持一致(除了临时复制滞后)。这个原则被称为状态机复制[60],我们将在第11章中回到它。 -类似地,可以使用总订单广播来实现可序列化的事务:如第242页上的“实际的串行执行”中所述,如果每个消息表示一个确定性事务作为存储过程来执行,并且每个节点都处理这些消息相同的顺序,那么数据库的分区和副本保持一致[61]。 +总订单广播正是您所需的数据库复制:如果每封邮件都表示写入数据库,并且每个副本按相同的顺序处理相同的写入,则副本将保持一致(除了临时复制滞后)。这个原则被称为状态机复制【60】,我们将在第11章中回到它。 +类似地,可以使用总订单广播来实现可序列化的事务:如第242页上的“实际的串行执行”中所述,如果每个消息表示一个确定性事务作为存储过程来执行,并且每个节点都处理这些消息相同的顺序,那么数据库的分区和副本保持一致【61】。 总订单广播的一个重要方面是订单在交付消息时是固定的:如果后续消息已经交付,节点不允许追溯地将消息插入订单中的较早位置。这个事实使得全部命令广播比时间戳命令更强。 查看总订单广播的另一种方式是创建日志(如在复制日志,事务日志或预写日志中):传递消息就像附加到日志。由于所有节点必须以相同的顺序传递相同的消息,因此所有节点都可以读取日志并看到相同的消息序列。 -全面订购广播对于实施提供防护令牌的锁定服务也很有用(请参见第294页的“防护令牌”)。每个获取锁的请求都作为消息添加到日志中,并且所有消息都按它们在日志中出现的顺序依次编号。序列号可以作为一个击剑标记,因为它是单调递增的。在ZooKeeper中,这个序列号被称为zxid [15]。 +全面订购广播对于实施提供防护令牌的锁定服务也很有用(请参见第294页的“防护令牌”)。每个获取锁的请求都作为消息添加到日志中,并且所有消息都按它们在日志中出现的顺序依次编号。序列号可以作为一个击剑标记,因为它是单调递增的。在ZooKeeper中,这个序列号被称为`zxid` 【15】。 #### 使用全序广播实现线性化的存储 如图9-4所示,在可线性化的系统中,有一个操作的总顺序。这是否意味着线性化与总订单播放相同?不完全,但两者之间有密切的联系[^x]。 -[^x]: 从形式上讲,可线性读写寄存器是一个“更容易”的问题。 总订单广播等同于共识[67],在异步崩溃停止模型[68]中没有确定性的解决方案,而可线性化的读写寄存器可以在同一系统模型中实现[23,24,25]。 然而,支持原子操作,如比较和设置,或者在寄存器中增加和获取,使得它相当于共识[28]。 因此,共识问题和可线性化的注册问题密切相关。 +[^x]: 从形式上讲,可线性读写寄存器是一个“更容易”的问题。 总订单广播等同于共识【67】,在异步崩溃停止模型【68】中没有确定性的解决方案,而可线性化的读写寄存器可以在同一系统模型中实现【23,24,25】。 然而,支持原子操作,如比较和设置,或者在寄存器中增加和获取,使得它相当于共识【28】。 因此,共识问题和可线性化的注册问题密切相关。 全部订单广播是异步的:消息被保证以固定的顺序可靠地传送,但是不能保证消息何时被传送(所以一个接收者可能落后于其他接收者)。相比之下,线性化是最近的保证:读取保证看到写入的最新值。 @@ -504,27 +506,27 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 想象一下,对于每一个可能的用户名,你都可以拥有一个带有原子比较和设置操作的线性化寄存器。每个寄存器最初的值为空值(表示不使用用户名)。当用户想要创建一个用户名时,对该用户名的注册表执行比较设置操作,在前一个注册值为空的情况下,将其设置为用户账号。如果多个用户试图同时获取相同的用户名,则只有一个比较和设置操作会成功,因为其他用户将看到非空值(由于线性化)。 -您可以通过使用全部命令广播作为仅追加日志[62,63]来执行如下可线性化的比较和设置操作: +您可以通过使用全部命令广播作为仅追加日志【62,63】来执行如下可线性化的比较和设置操作: 1. 在日志中添加一条消息,暂时指明您要声明的用户名。 2. 阅读日志,并等待你附加的信息被传回给你。[^xi] 3. 检查是否有任何消息声称你想要的用户名。如果所需用户名的第一条消息是你自己的消息,那么你是成功的:你可以提交用户名声明(也许通过附加另一条消息到日志)并确认给客户端。如果所需用户名的第一条消息来自其他用户,则中止操作。 -[^xi]: 如果您不等待,但是在入队之后立即确认写入,则会得到类似于多核x86处理器的内存一致性模型[43]。 该模型既不是线性的也不是连续的。 +[^xi]: 如果您不等待,但是在入队之后立即确认写入,则会得到类似于多核x86处理器的内存一致性模型【43】。 该模型既不是线性的也不是连续的。 -由于日志条目以相同顺序传递到所有节点,因此如果有多个并发写入,则所有节点将首先同意哪个节点。选择第一个冲突的写入作为胜利者,并中止后面的写入,确保所有节点都同意写入是提交还是中止。一个类似的方法可以用来在一个日志之上实现可序列化的多对象事务[62]。 +由于日志条目以相同顺序传递到所有节点,因此如果有多个并发写入,则所有节点将首先同意哪个节点。选择第一个冲突的写入作为胜利者,并中止后面的写入,确保所有节点都同意写入是提交还是中止。一个类似的方法可以用来在一个日志之上实现可序列化的多对象事务【62】。 -虽然此过程确保可线性写入,但不能保证线性化读取 - 如果您从与日志异步更新的存储中读取数据,则可能是陈旧的。 (具体来说,这里描述的过程提供了顺序一致性[47,64],有时也称为时间线一致性[65,66],这比线性化要弱一些)。为了使读取线性化,有几个选项: +虽然此过程确保可线性写入,但不能保证线性化读取 - 如果您从与日志异步更新的存储中读取数据,则可能是陈旧的。 (具体来说,这里描述的过程提供了顺序一致性【47,64】,有时也称为时间线一致性【65,66】,这比线性化要弱一些)。为了使读取线性化,有几个选项: -* 您可以通过附加消息,读取日志以及在消息被传回给您时执行实际读取来对日志进行排序。消息在日志中的位置因此定义了读取发生的时间点。 (法定读取etcd的工作有点像这样[16]。) -* 如果日志允许以线性方式获取最新日志消息的位置,则可以查询该位置,等待直到该位置的所有条目传送给您,然后执行读取。 (这是Zoo-Keeper的sync()操作背后的思想[15])。 -* 您可以从写入时同步更新的副本进行读取,因此可以确保最新。 (这种技术用于链式复制[63];另请参阅第155页上的“复制研究”。) +* 您可以通过附加消息,读取日志以及在消息被传回给您时执行实际读取来对日志进行排序。消息在日志中的位置因此定义了读取发生的时间点。 (法定读取etcd的工作有点像这样【16】。) +* 如果日志允许以线性方式获取最新日志消息的位置,则可以查询该位置,等待直到该位置的所有条目传送给您,然后执行读取。 (这是Zookeeper的`sync()`操作背后的思想【15】)。 +* 您可以从写入时同步更新的副本进行读取,因此可以确保最新。 (这种技术用于链式复制【63】;另请参阅第155页上的“复制研究”。) #### 使用线性化存储实现总订单广播 最后一节介绍了如何从全部命令广播中构建一个线性化的比较和设置操作。我们也可以把它转过来,假设我们有可线性化的存储,并展示如何从它构建全部命令播放。 -最简单的方法是假设你有一个线性化的寄存器来存储一个整数,并且有一个原子增量和获取操作[28]。或者,原子比较和设置操作也可以完成这项工作。 +最简单的方法是假设你有一个线性化的寄存器来存储一个整数,并且有一个原子增量和获取操作【28】。或者,原子比较和设置操作也可以完成这项工作。 该算法很简单:对于每个要通过全部订单广播发送的消息,您将递增并获取可线性化的整数,然后将从寄存器获得的值作为序号附加到消息中。然后,您可以将消息发送到所有节点(重新发送任何丢失的消息),并且收件人将按序号连续发送消息。 @@ -532,9 +534,9 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 与Lamport时间戳 - 事实上,这是总订单广播和时间戳订购之间的关键区别。 -使用原子增量和获取操作来创建线性化整数有多困难?像往常一样,如果事情从来没有失败过,那很容易:你可以把它保存在一个节点的变量中。问题在于处理当该节点的网络连接中断时的情况,并在该节点失败时恢复该值[59]。一般来说,如果你对可线性化序列号的产生者认真思考,你不可避免地会得出一个一致的算法。 +使用原子增量和获取操作来创建线性化整数有多困难?像往常一样,如果事情从来没有失败过,那很容易:你可以把它保存在一个节点的变量中。问题在于处理当该节点的网络连接中断时的情况,并在该节点失败时恢复该值【59】。一般来说,如果你对可线性化序列号的产生者认真思考,你不可避免地会得出一个一致的算法。 -这并非巧合:可以证明,线性化的比较和设置(或增量和取得)寄存器和全部命令广播都相当于[28,67]。也就是说,如果你能解决其中的一个问题,你可以把它转化成为其他问题的解决方案。这是相当深刻和令人惊讶的洞察力! +这并非巧合:可以证明,线性化的比较和设置(或增量和取得)寄存器和全部命令广播都相当于【28,67】。也就是说,如果你能解决其中的一个问题,你可以把它转化成为其他问题的解决方案。这是相当深刻和令人惊讶的洞察力! 现在是时候正面处理共识问题了,我们将在本章的其余部分进行讨论。 @@ -555,16 +557,16 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 在支持跨越多个节点或分区的事务的数据库中,有一个事务可能在某些节点上失败,但在其他节点上成功。如果我们想要维护事务的原子性(就ACID而言,请参阅第223页的“原子性”),我们必须让所有节点对事务的结果达成一致:要么全部中止/回滚(如果出现任何错误)或者他们都承诺(如果没有出错)。这个共识的例子被称为原子提交问题[^xii]。 -[^]: 原子提交的形式化与共识稍有不同:原子事务只有在所有参与者投票提交的情况下才能提交,如果有任何参与者需要中止,则必须中止。 允许共识决定其中一位参与者提出的任何价值。 然而,原子的承诺和共识是可以相互压缩的[70,71]。 非阻塞原子提交比共识更难 - 请参阅第359页上的“三阶段提交”。 +[^]: 原子提交的形式化与共识稍有不同:原子事务只有在所有参与者投票提交的情况下才能提交,如果有任何参与者需要中止,则必须中止。 允许共识决定其中一位参与者提出的任何价值。 然而,原子的承诺和共识是可以相互压缩的【70,71】。 非阻塞原子提交比共识更难 - 请参阅第359页上的“三阶段提交”。 > ### 共识的不可能性 > -> 您可能已经听说过作者Fischer,Lynch和Paterson之后的FLP结果[68],这证明如果存在节点可能崩溃的风险,则不存在总是能够达成一致的算法。在分布式系统中,我们必须假设节点可能会崩溃,所以可靠的共识是不可能的。然而,在这里,我们正在讨论达成共识的算法。这里发生了什么? +> 您可能已经听说过作者Fischer,Lynch和Paterson之后的FLP结果【68】,这证明如果存在节点可能崩溃的风险,则不存在总是能够达成一致的算法。在分布式系统中,我们必须假设节点可能会崩溃,所以可靠的共识是不可能的。然而,在这里,我们正在讨论达成共识的算法。这里发生了什么? > -> 答案是FLP结果在异步系统模型中得到了证明(请参阅“系统模型与现实”在本部分),这是一个非常有限的模型,它假定确定性算法不能使用任何时钟或超时。如果算法被允许使用超时或其他方法来识别可疑的崩溃节点(即使怀疑有时是错误的),那么共识就变得可以解决了[67]。即使只允许算法使用随机数也足以绕过不可能的结果[69]。 +> 答案是FLP结果在异步系统模型中得到了证明(请参阅“系统模型与现实”在本部分),这是一个非常有限的模型,它假定确定性算法不能使用任何时钟或超时。如果算法被允许使用超时或其他方法来识别可疑的崩溃节点(即使怀疑有时是错误的),那么共识就变得可以解决了【67】。即使只允许算法使用随机数也足以绕过不可能的结果【69】。 > 因此,FLP虽然不可能达成共识,但理论上具有重要意义,但实际上分布式系统通常可以达成共识。 -在本节中,我们将首先更详细地检查原子提交问题。具体来说,我们将讨论两阶段提交(2PC)算法,这是解决原子提交最常见的方法,并在各种数据库,消息传递系统和应用服务器中实现。事实证明,2PC是一种一致的算法,但不是一个很好的[70,71]。 +在本节中,我们将首先更详细地检查原子提交问题。具体来说,我们将讨论两阶段提交(2PC)算法,这是解决原子提交最常见的方法,并在各种数据库,消息传递系统和应用服务器中实现。事实证明,2PC是一种一致的算法,但不是一个很好的【70,71】。 通过从2PC学习,我们将继续努力实现更好的一致性算法,比如ZooKeeper(Zab)和etcd(Raft)中使用的算法。 @@ -580,7 +582,7 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 对于在单个数据库节点执行的事务,原子性通常由存储引擎执行。当客户端请求数据库节点提交事务时,数据库使事务的写入持久化(通常在预先写好的日志中;请参阅第82页的“使B树可靠”),然后将提交记录追加到日志中磁盘。如果数据库在这个过程中间崩溃,当节点重新启动时,事务从日志中恢复:如果提交记录在崩溃之前成功地写入磁盘,则认为事务被提交;如果不是,则来自该事务的任何写入都被回滚。 -因此,在单个节点上,事务承诺主要取决于数据持久写入磁盘的顺序:首先是数据,然后是提交记录[72]。事务提交或放弃的关键决定时刻是磁盘完成写入提交记录的时刻:在此之前,仍有可能中止(由于崩溃),但在此之后,事务提交 - 特德(即使数据库崩溃)。因此,这是一个单一的设备(一个特定的磁盘驱动器的控制器,连接到一个特定的节点),使提交原子。 +因此,在单个节点上,事务承诺主要取决于数据持久写入磁盘的顺序:首先是数据,然后是提交记录【72】。事务提交或放弃的关键决定时刻是磁盘完成写入提交记录的时刻:在此之前,仍有可能中止(由于崩溃),但在此之后,事务提交 - 特德(即使数据库崩溃)。因此,这是一个单一的设备(一个特定的磁盘驱动器的控制器,连接到一个特定的节点),使提交原子。 但是,如果一个事务中涉及多个节点呢?例如,也许在分区数据库中有一个多对象事务,或者是一个由术语分区的二级索引(其中索引条目可能位于与主数据不同的节点上;请参阅“分区和二级索引”第206页)。大多数“NoSQL”分布式数据存储不支持这种分布式事务,而是各种集群关系系统(请参见“实践中的分布式事务”)。 @@ -594,7 +596,7 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 事务提交必须是不可撤销的 - 您不得改变主意,并在交易提交后追溯中止交易。这个规则的原因是,一旦数据被提交,其他交易就可以看到,因此其他客户可能会开始依赖这些数据。这个原则构成了读取提交隔离的基础,在“读取提交”一节中讨论了这个问题。如果一个事务在提交后被允许中止,所有读取提交数据的事务将基于被追溯声明不存在的数据所以他们也必须恢复。 -(承诺交易的效果有可能在后来被另一个补偿交易取消[73,74],但从数据库的角度来看,这是一个单独的交易,因此任何交叉交易的正确性要求是应用程序的问题。) +(承诺交易的效果有可能在后来被另一个补偿交易取消【73,74】,但从数据库的角度来看,这是一个单独的交易,因此任何交叉交易的正确性要求是应用程序的问题。) #### 介绍两阶段提交 @@ -657,17 +659,17 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 两阶段提交被称为阻塞原子提交协议,因为2PC可能卡住等待协调器恢复。理论上,可以使一个原子提交协议非阻塞,以便在节点失败时不会卡住。但是,在实践中做这个工作并不那么简单。 -作为2PC的替代方案,已经提出了一种称为三阶段提交(3PC)的算法[13,80]。然而,3PC假定一个有界延迟的网络和有限响应时间的节点;在大多数具有无限网络延迟和进程暂停的实际系统中(见第8章),它不能保证原子性。 +作为2PC的替代方案,已经提出了一种称为三阶段提交(3PC)的算法【13,80】。然而,3PC假定一个有界延迟的网络和有限响应时间的节点;在大多数具有无限网络延迟和进程暂停的实际系统中(见第8章),它不能保证原子性。 -通常,非阻塞原子提交需要一个完美的故障检测器[67,71] - 即一个可靠的机制来判断一个节点是否已经崩溃。在无限延迟的网络中,超时不是可靠的故障检测器,因为即使没有节点崩溃,请求也可能由于网络问题而超时。出于这个原因,2PC继续被使用,尽管协调器故障的已知问题。 +通常,非阻塞原子提交需要一个完美的故障检测器【67,71】 - 即一个可靠的机制来判断一个节点是否已经崩溃。在无限延迟的网络中,超时不是可靠的故障检测器,因为即使没有节点崩溃,请求也可能由于网络问题而超时。出于这个原因,2PC继续被使用,尽管协调器故障的已知问题。 ### 实践中的分布式事务 -分布式事务,尤其是那些通过两阶段提交实现的事务,声誉混杂。一方面,它们被看作是提供一个难以实现的重要的安全保证;另一方面,他们被批评为造成运营问题,造成业绩下滑,承诺超过他们能够实现的目标[81,82,83,84]。许多云服务由于其产生的操作问题而选择不执行分布式事务[85,86]。 +分布式事务,尤其是那些通过两阶段提交实现的事务,声誉混杂。一方面,它们被看作是提供一个难以实现的重要的安全保证;另一方面,他们被批评为造成运营问题,造成业绩下滑,承诺超过他们能够实现的目标【81,82,83,84】。许多云服务由于其产生的操作问题而选择不执行分布式事务【85,86】。 -分布式事务的某些实现会带来严重的性能损失 - 例如,MySQL中的分布式事务被报告比单节点事务慢10倍以上[87],所以当人们建议不要使用这些事务时就不足为奇了。两阶段提交所固有的大部分性能成本是由于崩溃恢复所需的额外磁盘强制(fsync)[88]以及额外的网络往返。 +分布式事务的某些实现会带来严重的性能损失 - 例如,MySQL中的分布式事务被报告比单节点事务慢10倍以上【87】,所以当人们建议不要使用这些事务时就不足为奇了。两阶段提交所固有的大部分性能成本是由于崩溃恢复所需的额外磁盘强制(fsync)【88】以及额外的网络往返。 但是,我们不应该直接抛弃分布式交易,而应该更加详细地审视这些交易,因为从中可以汲取重要的经验教训。首先,我们应该精确地说明“分布式交易”的含义。两种截然不同的分布式交易类型经常被混淆: @@ -693,7 +695,7 @@ Lamport时间戳有时会与版本向量混淆,我们在第184页上的“检 #### XA事务 -X/Open XA(**扩展架构(eXtended Architecture)**的缩写)是跨异构技术实现两阶段提交的标准[76,77]。它于1991年推出并得到了广泛的实施:许多传统关系数据库(包括PostgreSQL,MySQL,DB2,SQL Server和Oracle)和消息代理(包括ActiveMQ,HornetQ,MSMQ和IBM MQ) 。 +X/Open XA(**扩展架构(eXtended Architecture)**的缩写)是跨异构技术实现两阶段提交的标准【76,77】。它于1991年推出并得到了广泛的实施:许多传统关系数据库(包括PostgreSQL,MySQL,DB2,SQL Server和Oracle)和消息代理(包括ActiveMQ,HornetQ,MSMQ和IBM MQ) 。 XA不是一个网络协议 - 它只是一个用于与事务协调器连接的C API。此API的绑定以其他语言存在;例如,在Java EE应用程序的世界中,XA事务是使用Java事务API(JTA)实现的,而Java事务API(JTA)则由许多用于使用Java数据库连接(JDBC)的数据库驱动程序以及使用Java消息服务(JMS)API。 @@ -714,13 +716,13 @@ XA假定您的应用程序使用网络驱动程序或客户端库来与参与者 #### 从协调器故障中恢复 -理论上,如果协调器崩溃并重新启动,它应该干净地从日志中恢复其状态,并解决任何有问题的事务。然而,在实践中,孤立的不确定交易确实发生[89,90],也就是说,协调者不能以任何理由决定结果的交易(例如,因为交易日志已经由于软件错误)。这些交易不能自动解决,所以他们永远坐在数据库中,持有锁和阻止其他交易。 +理论上,如果协调器崩溃并重新启动,它应该干净地从日志中恢复其状态,并解决任何有问题的事务。然而,在实践中,孤立的不确定交易确实发生【89,90】,也就是说,协调者不能以任何理由决定结果的交易(例如,因为交易日志已经由于软件错误)。这些交易不能自动解决,所以他们永远坐在数据库中,持有锁和阻止其他交易。 即使重新启动数据库服务器也不能解决这个问题,因为2PC的正确实现必须在重新启动时保留一个有问题的事务的锁(否则就会冒违反原子性保证的风险)。这是一个棘手的情况。 唯一的出路是让管理员手动决定是提交还是回滚事务。管理员必须检查每个有问题的交易的参与者,确定是否有任何参与者已经提交或中止,然后将相同的结果应用于其他参与者。解决这个问题潜在地需要大量的人工努力,并且在严重的生产中断期间(否则,为什么协调员处于这样一个糟糕的状态),很可能需要在高压力和时间压力下完成。 -许多XA的实现都有一个叫做启发式决策的紧急逃生舱口:允许参与者单方面决定放弃或进行一个有疑问的交易,而不需要协调员做出明确的决定[76,77,91]。要清楚的是,这里的平庸是可能破坏原子性的委婉说法,因为它违背了两阶段承诺的承诺体系。因此,启发式决策只是为了摆脱灾难性的情况,而不是经常使用。 +许多XA的实现都有一个叫做启发式决策的紧急逃生舱口:允许参与者单方面决定放弃或进行一个有疑问的交易,而不需要协调员做出明确的决定【76,77,91】。要清楚的是,这里的平庸是可能破坏原子性的委婉说法,因为它违背了两阶段承诺的承诺体系。因此,启发式决策只是为了摆脱灾难性的情况,而不是经常使用。 #### 分布式事务的限制 @@ -728,7 +730,7 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 * 如果协调器没有被复制,而是只在一台机器上运行,那么整个系统是一个失败的单点(因为它的失败导致其他应用程序服务器阻塞在有问题的事务处理的锁上)。令人惊讶的是,许多协调器实现默认情况下不是高度可用,或者只有基本的复制支持。 * 许多服务器端应用程序都是在无状态模式下开发的(受到HTTP的青睐),所有持久状态都存储在数据库中,具有应用程序服务器可随意添加和删除的优点。但是,当协调器是应用程序服务器的一部分时,它会改变部署的性质。突然间,协调员的日志成为持久系统状态的关键部分 - 与数据库本身一样重要,因为协调员日志是为了在崩溃后恢复疑问交易所必需的。这样的应用程序服务器不再是无状态的。 -* 由于XA需要与各种数据系统兼容,因此这是必须的最低公分母。例如,它不能检测到不同系统间的死锁(因为这将需要一个标准化的协议来让系统交换每个事务正在等待的锁的信息),而且它不适用于SSI(参见“可串行快照隔离(SSI) “第261页),因为这需要一个协议来识别不同系统之间的冲突。 +* 由于XA需要与各种数据系统兼容,因此这是必须的最低公分母。例如,它不能检测到不同系统间的死锁(因为这将需要一个标准化的协议来让系统交换每个事务正在等待的锁的信息),而且它不适用于[SSI](ch7.md#可串行快照隔离(SSI) ),因为这需要一个协议来识别不同系统之间的冲突。 * 对于数据库内部的分布式事务(而不是XA),限制不是很大,例如SSI的分布式版本是可能的。然而,仍然存在2PC成功进行交易的问题,所有参与者都必须作出回应。因此,如果系统的任何部分损坏,交易也会失败。因此,分布式事务有扩大故障的趋势,这与我们构建容错系统的目标背道而驰。 这些事实是否意味着我们应该放弃保持几个系统一致的所有希望?不完全 - 有其他的方法可以让我们在没有异构分布式事务的痛苦的情况下实现同样的事情。我们将在第十一章和第十二章回到这些章节。但首先,我们应该总结一致的话题。 @@ -739,9 +741,9 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 非正式地,共识意味着让几个节点达成一致。例如,如果有几个人同时尝试预订飞机上的最后一个座位或剧院中的同一个座位,或者尝试使用相同的用户名注册一个帐户,则可以使用一个一致的算法来确定哪个其中一个互不相容的行动应该是赢家。 -共识问题通常形式化如下:一个或多个节点可以提出值,并且共识算法决定其中的一个值。在座位预订的例子中,当几个顾客同时试图购买最后一个座位时,处理顾客请求的每个节点可以提出正在服务的顾客的ID,并且决定指示哪个顾客获得座位。在这种形式主义中,共识算法必须满足以下性质[25]:[^xiii] +共识问题通常形式化如下:一个或多个节点可以提出值,并且共识算法决定其中的一个值。在座位预订的例子中,当几个顾客同时试图购买最后一个座位时,处理顾客请求的每个节点可以提出正在服务的顾客的ID,并且决定指示哪个顾客获得座位。在这种形式主义中,共识算法必须满足以下性质【25】:[^xiii] -[^xiii]: 这种共识的特殊形式被称为统一共识,相当于在具有不可靠故障检测器的异步系统中的常规共识[71]。学术文献通常指的是过程而不是节点,但我们在这里使用节点来与本书的其余部分保持一致。 +[^xiii]: 这种共识的特殊形式被称为统一共识,相当于在具有不可靠故障检测器的异步系统中的常规共识【71】。学术文献通常指的是过程而不是节点,但我们在这里使用节点来与本书的其余部分保持一致。 ***一致同意*** @@ -762,23 +764,23 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 如果你不关心容错,那么满足前三个属性很容易:你可以将一个节点硬编码为“独裁者”,并让该节点做出所有的决定。但是,如果一个节点失败,那么系统就不能再做出任何决定。事实上,这就是我们在两阶段承诺的情况下所看到的:如果协调员失败了,那么不确定的参与者就不能决定是否提交或中止。 -终止财产正式形成了容错的思想。它基本上说,一个共识算法不能简单地坐下来,永远不要做任何事 - 换句话说,它必须取得进展。即使有些节点出现故障,其他节点也必须做出决定。 (终止是一种活泼的财产,而另外三种是安全财产 - 参见第308页上的“安全和活力”。) +终止属性正式形成了容错的思想。它基本上说,一个共识算法不能简单地坐下来,永远不要做任何事 - 换句话说,它必须取得进展。即使有些节点出现故障,其他节点也必须做出决定。 (终止是一种活泼的财产,而另外三种是安全属性——参见“[安全性和活性](ch8.md#安全性和活性)”。) 共识的系统模型假设,当一个节点“崩溃”时,它突然消失,永远不会回来。 (而不是软件崩溃,想象一下地震,包含你的节点的数据中心被山体滑坡所摧毁,你必须假设你的节点被埋在30英尺以下的泥土中,并且永远不会回到在线状态。)这个系统模型,任何等待节点恢复的算法都不能满足终止属性。特别是2PC不符合终止的要求。 -当然,如果所有的节点都崩溃,而且没有一个正在运行,那么任何算法都不可能决定什么。算法可以容忍的失败次数有一个限制:事实上,可以证明任何一致性算法都需要至少大部分节点正确运行,以确保终止[67]。大多数人可以安全地形成法定人数(请参阅第179页上的“读和写的法定人数”)。 +当然,如果所有的节点都崩溃,而且没有一个正在运行,那么任何算法都不可能决定什么。算法可以容忍的失败次数有一个限制:事实上,可以证明任何一致性算法都需要至少大部分节点正确运行,以确保终止【67】。大多数人可以安全地形成法定人数(请参阅第179页上的“读和写的法定人数”)。 -因此,终止属性受到不到一半的节点崩溃或不可达的假设。然而,即使大多数节点出现故障或存在严重的网络问题,大多数共识的实施都能确保始终满足安全属性 - 协议,完整性和有效性[92]。因此,大规模的中断可能会阻止系统处理请求,但是它不能通过使系统做出无效的决定来破坏共识系统。 +因此,终止属性受到不到一半的节点崩溃或不可达的假设。然而,即使大多数节点出现故障或存在严重的网络问题,大多数共识的实施都能确保始终满足安全属性 - 协议,完整性和有效性【92】。因此,大规模的中断可能会阻止系统处理请求,但是它不能通过使系统做出无效的决定来破坏共识系统。 -大多数一致性算法假定没有拜占庭式的错误,正如在“拜占庭式故障”一节中所讨论的那样。也就是说,如果一个节点没有正确地遵循协议(例如,如果它发送矛盾的消息到不同的节点),它可能会破坏协议的安全属性。只要少于三分之一的节点是拜占庭故障[25,93],就可以对拜占庭故障形成共识,但我们没有空间在本书中详细讨论这些算法。 +大多数一致性算法假定没有拜占庭式的错误,正如在“拜占庭式故障”一节中所讨论的那样。也就是说,如果一个节点没有正确地遵循协议(例如,如果它发送矛盾的消息到不同的节点),它可能会破坏协议的安全属性。只要少于三分之一的节点是拜占庭故障【25,93】,就可以对拜占庭故障形成共识,但我们没有空间在本书中详细讨论这些算法。 #### 共识算法和总订单广播 -最着名的容错一致性算法是**视图戳复制(viewstamped replication)**(VSR)[94,95],Paxos [96,97,98,99],Raft [22,100,101]和Zab [15,21,102] 。这些算法之间有相当多的相似之处,但它们并不相同[103]。在本书中,我们不会详细介绍不同的算法:除非你自己实现一个共识系统(这可能不是一个明智的做法),只要了解一些共同的高级思想就足够了这很难[98,104])。 +最着名的容错一致性算法是**视图戳复制(viewstamped replication)**(VSR)【94,95】,Paxos 【96,97,98,99】,Raft 【22,100,101】和Zab 【15,21,102】 。这些算法之间有相当多的相似之处,但它们并不相同【103】。在本书中,我们不会详细介绍不同的算法:除非你自己实现一个共识系统(这可能不是一个明智的做法),只要了解一些共同的高级思想就足够了这很难【98,104】)。 这些算法中的大多数实际上并不直接使用这里描述的形式化模型(建议和决定单个值,同时满足协议,完整性,有效性和终止性质)。相反,他们决定了一系列的值,这使得他们成为了订单广播算法,正如本章前面所讨论的那样(请参阅第348页上的“全部订单广播”)。 -请记住,总订单广播要求将消息按照相同的顺序准确传送到所有节点。如果你仔细想想,这相当于进行了几轮的共识:在每一轮中,节点提出下一个要发送的消息,然后决定下一个要发送的消息总数[67]。 +请记住,总订单广播要求将消息按照相同的顺序准确传送到所有节点。如果你仔细想想,这相当于进行了几轮的共识:在每一轮中,节点提出下一个要发送的消息,然后决定下一个要发送的消息总数【67】。 所以,总的订单广播相当于重复的一轮共识(每个共同的决定对应于一个消息传递): @@ -810,9 +812,9 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 在任何领导人被允许决定任何事情之前,必须首先检查是否没有其他具有较高时代的领导者,这可能会采取相互冲突的决定。领导者如何知道它没有被另一个节点赶下?回想一下第300页的“真理是由多数人定义的”:一个节点不一定相信自己的判断 - 只是因为节点认为它是领导者,并不一定意味着其他节点接受它作为他们的领导者。 -相反,它必须从节点法定人数中收集选票(请参阅第179页上的“读和写的法定人数”)。对于领导者想要做出的每一个决定,都必须将建议值发送给其他节点,并等待法定人数的节点响应提案。法定人数通常但不总是由大部分节点组成[105]。一个节点只有在没有意识到任何具有更高纪元的其他领导者的时候才投票赞成。 +相反,它必须从节点法定人数中收集选票(请参阅第179页上的“读和写的法定人数”)。对于领导者想要做出的每一个决定,都必须将建议值发送给其他节点,并等待法定人数的节点响应提案。法定人数通常但不总是由大部分节点组成【105】。一个节点只有在没有意识到任何具有更高纪元的其他领导者的时候才投票赞成。 -因此,我们有两轮投票:一次是选一位领导人,二是投票领导人的提议。关键的看法是,这两票的法定人数必须重叠:如果一个提案的投票成功,至少有一个投票的节点也必须参加最近的领导人选举[105]。因此,如果一个提案的投票没有显示任何更高的时代,那么现在的领导者就可以得出这样的结论:没有一个更高时代的领袖选举发生了,因此可以确定它仍然是领导。然后它可以安全地决定提出的价值。 +因此,我们有两轮投票:一次是选一位领导人,二是投票领导人的提议。关键的看法是,这两票的法定人数必须重叠:如果一个提案的投票成功,至少有一个投票的节点也必须参加最近的领导人选举【105】。因此,如果一个提案的投票没有显示任何更高的时代,那么现在的领导者就可以得出这样的结论:没有一个更高时代的领袖选举发生了,因此可以确定它仍然是领导。然后它可以安全地决定提出的价值。 这个投票过程看起来很像两阶段提交。最大的区别是在2PC中协调器不是选出来的,而容错协议算法只需要大部分节点的投票,而2PC则要求每个参与者都做“是”的投票。而且,共识算法定义了一个恢复过程,通过这个过程,节点可以在选举出新的领导者之后进入一个一致的状态,确保总是满足安全属性。这些差异是共识算法的正确性和容错性的关键。 @@ -830,7 +832,7 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 共识系统通常依靠超时来检测失败的节点。在网络延迟高度变化的环境中,特别是在地理上分布的系统中,经常发生一个节点错误地认为由于暂时的网络问题,导致失败的原因。虽然这个错误不会损害安全属性,但频繁的领导者选举会导致糟糕的表现,因为系统最终会花费更多的时间来选择领导者而不是做任何有用的工作。 -有时,共识算法对网络问题特别敏感。例如,Raft已被证明有不愉快的边缘情况[106]:如果整个网络工作正常,除了一个特定的网络连接一直不可靠,Raft可以进入领导层不断在两个节点之间弹跳的情况,或者目前的领导者不断被迫辞职,所以这个制度从来没有取得进展。其他一致性算法也存在类似的问题,而对不可靠网络更具鲁棒性的设计算法仍然是一个开放的研究问题。 +有时,共识算法对网络问题特别敏感。例如,Raft已被证明有不愉快的边缘情况【106】:如果整个网络工作正常,除了一个特定的网络连接一直不可靠,Raft可以进入领导层不断在两个节点之间弹跳的情况,或者目前的领导者不断被迫辞职,所以这个制度从来没有取得进展。其他一致性算法也存在类似的问题,而对不可靠网络更具鲁棒性的设计算法仍然是一个开放的研究问题。 ### 成员与协调服务 @@ -840,7 +842,7 @@ XA事务解决了保持多个参与者数据系统一致的真实而重要的问 ZooKeeper和etcd被设计为容纳少量完全可以放在内存中的数据(虽然它们仍然写入磁盘以保持持久性),所以你不希望在这里存储所有的应用程序的数据。使用容错全序广播算法在所有节点上复制少量的数据。正如前面所讨论的那样,全部命令广播就是数据库复制所需要的:如果每条消息代表对数据库的写入,则以相同的顺序应用相同的写入操作可以保持副本之间的一致性。 -ZooKeeper模仿Google的Chubby锁定服务[14,98],不仅实现了全面的命令广播(因此也实现了共识),而且还构建了一组有趣的其他特性,这些特性在构建分布式系统时变得特别有用: +ZooKeeper模仿Google的Chubby锁定服务【14,98】,不仅实现了全面的命令广播(因此也实现了共识),而且还构建了一组有趣的其他特性,这些特性在构建分布式系统时变得特别有用: ***线性化的原子操作*** @@ -848,7 +850,7 @@ ZooKeeper模仿Google的Chubby锁定服务[14,98],不仅实现了全面的命 ***操作的总排序*** -如“页首301和锁定”中所述,当某个资源受到锁定或租约的保护时,您需要一个防护令牌来防止客户端在进程暂停的情况下彼此冲突。击剑标记是每次获得锁定时单调增加的数字。 ZooKeeper通过完全排序所有操作,并为每个操作提供一个单调递增的事务ID(zxid)和版本号(cversion)来提供这个功能[15]。 +如“页首301和锁定”中所述,当某个资源受到锁定或租约的保护时,您需要一个防护令牌来防止客户端在进程暂停的情况下彼此冲突。击剑标记是每次获得锁定时单调增加的数字。 ZooKeeper通过完全排序所有操作,并为每个操作提供一个单调递增的事务ID(zxid)和版本号(cversion)来提供这个功能【15】。 ***故障检测*** @@ -864,27 +866,27 @@ ZooKeeper模仿Google的Chubby锁定服务[14,98],不仅实现了全面的命 #### 将工作分配给节点 -ZooKeeper / Chubby模型运行良好的一个例子是,如果您有几个流程或服务的实例,并且需要选择其中一个实例作为leader或primary。如果领导失败,其他节点之一应该接管。这对于单引导数据库当然是有用的,但对于作业调度程序和类似的有状态系统也是有用的。 +ZooKeeper/Chubby模型运行良好的一个例子是,如果您有几个流程或服务的实例,并且需要选择其中一个实例作为leader或primary。如果领导失败,其他节点之一应该接管。这对于单引导数据库当然是有用的,但对于作业调度程序和类似的有状态系统也是有用的。 另一个例子是,当你有一些分区资源(数据库,消息流,文件存储,分布式参与者系统等),并需要决定将哪个分区分配给哪个节点时。当新节点加入群集时,需要将某些分区从现有节点移动到新节点,以便重新平衡负载(请参阅第195页的“重新平衡分区”)。当节点被移除或失败时,其他节点需要接管失败节点的工作。 -这些类型的任务可以通过在ZooKeeper中明智地使用原子操作,各种节点和通知来实现。如果正确完成,这种方法允许应用程序自动从故障中恢复,无需人工干预。尽管Apache Curator [17]等库已经出现在ZooKeeper客户端API的顶层提供了更高级别的工具,但这样做并不容易,但它仍然比尝试从头开始实现必要的一致性算法要好得多,成绩不佳[107]。 +这些类型的任务可以通过在ZooKeeper中明智地使用原子操作,各种节点和通知来实现。如果正确完成,这种方法允许应用程序自动从故障中恢复,无需人工干预。尽管Apache Curator 【17】等库已经出现在ZooKeeper客户端API的顶层提供了更高级别的工具,但这样做并不容易,但它仍然比尝试从头开始实现必要的一致性算法要好得多,成绩不佳【107】。 应用程序最初只能在单个节点上运行,但最终可能会增长到数千个节点。试图在如此之多的节点上进行多数选票将是非常低效的。相反,ZooKeeper在固定数量的节点(通常是三到五个)上运行,并在这些节点之间执行其多数票,同时支持潜在的大量客户端。因此,ZooKeeper提供了一种将协调节点(共识,操作排序和故障检测)的一些工作“外包”到外部服务的方式。 -通常,由ZooKeeper管理的数据的类型变化十分缓慢:代表“分区7中的节点运行在10.1.1.23上”的信息可能会在几分钟或几小时的时间内发生变化。它不是用来存储应用程序的运行时状态的,每秒可能会改变数千甚至数百万次。如果应用程序状态需要从一个节点复制到另一个节点,则可以使用其他工具(如Apache BookKeeper [108])。 +通常,由ZooKeeper管理的数据的类型变化十分缓慢:代表“分区7中的节点运行在10.1.1.23上”的信息可能会在几分钟或几小时的时间内发生变化。它不是用来存储应用程序的运行时状态的,每秒可能会改变数千甚至数百万次。如果应用程序状态需要从一个节点复制到另一个节点,则可以使用其他工具(如Apache BookKeeper 【108】)。 #### 服务发现 -ZooKeeper,etcd和Consul也经常用于服务发现 - 也就是找出你需要连接到哪个IP地址才能到达特定的服务。在云数据中心环境中,虚拟机连续来去常见,您通常不会提前知道您的服务的IP地址。相反,您可以配置您的服务,使其在启动时注册服务注册表中的网络端点,然后可以由其他服务找到它们。 +ZooKeeper,etcd和Consul也经常用于服务发现——也就是找出你需要连接到哪个IP地址才能到达特定的服务。在云数据中心环境中,虚拟机连续来去常见,您通常不会提前知道您的服务的IP地址。相反,您可以配置您的服务,使其在启动时注册服务注册表中的网络端点,然后可以由其他服务找到它们。 -但是,服务发现是否需要达成共识还不太清楚。 DNS是查找服务名称的IP地址的传统方式,它使用多层缓存来实现良好的性能和可用性。从DNS读取是绝对不可线性化的,如果DNS查询的结果有点陈旧,通常不会有问题[109]。 DNS对网络中断的可靠性和可靠性更为重要。 +但是,服务发现是否需要达成共识还不太清楚。 DNS是查找服务名称的IP地址的传统方式,它使用多层缓存来实现良好的性能和可用性。从DNS读取是绝对不可线性化的,如果DNS查询的结果有点陈旧,通常不会有问题【109】。 DNS对网络中断的可靠性和可靠性更为重要。 尽管服务发现并不需要共识,但领导者选举却是如此。因此,如果您的共识系统已经知道领导是谁,那么也可以使用这些信息来帮助其他服务发现领导是谁。为此,一些共识系统支持只读缓存副本。这些副本异步接收共识算法所有决策的日志,但不主动参与投票。因此,它们能够提供不需要线性化的读取请求。 #### 成员服务 -ZooKeeper和朋友们可以看作是成员服务研究的悠久历史的一部分,这个历史可以追溯到20世纪80年代,并且对建立高度可靠的系统(例如空中交通管制)非常重要[110]。 +ZooKeeper和朋友们可以看作是成员服务研究的悠久历史的一部分,这个历史可以追溯到20世纪80年代,并且对建立高度可靠的系统(例如空中交通管制)非常重要【110】。 成员资格服务确定哪些节点当前处于活动状态并且是群集的活动成员。正如我们在第8章中看到的那样,由于无限的网络延迟,无法可靠地检测到另一个节点是否发生故障。但是,如果你通过一致的方式进行故障检测,那么节点可以就哪些节点应该被认为是存在或不存在达成一致。 @@ -932,19 +934,19 @@ ZooKeeper和朋友们可以看作是成员服务研究的悠久历史的一部 但是,如果单个领导失败,或者如果网络中断导致领导不可达,则这样的系统变得无法取得进展。处理这种情况有三种方法: -1. 等待领导者恢复,同时接受系统将被阻止。许多XA / JTA事务协调员选择这个选项。这种方法并不能完全解决共识,因为它不能满足终止财产的要求:如果领导者没有恢复,系统可以被永久封锁。 +1. 等待领导者恢复,同时接受系统将被阻止。许多XA/JTA事务协调员选择这个选项。这种方法并不能完全解决共识,因为它不能满足终止财产的要求:如果领导者没有恢复,系统可以被永久封锁。 2. 通过让人类选择一个新的领导者节点并重新配置系统来使用它来手动故障切换。许多关系数据库都采用这种方法。这是一种“上帝的行为”的共识 - 计算机系统之外的操作人员做出决定。故障转移的速度受到人类行动速度的限制,通常比计算机慢。 -3. 使用算法自动选择一个新的领导。这种方法需要一个一致的算法,建议使用经过验证的算法来正确处理不利的网络条件[107]。 +3. 使用算法自动选择一个新的领导。这种方法需要一个一致的算法,建议使用经过验证的算法来正确处理不利的网络条件【107】。 尽管一个单独的领导者数据库可以提供线性化,而不需要在每个写作上执行一致的算法,但是仍然需要达成共识以保持领导力和领导力的改变。因此,从某种意义上说,有一个领导者只是“把罐子放在路上”:共识还是需要的,只是在一个不同的地方,而不是频繁的。好消息是,容错算法和共识系统存在,我们在本章中简要地讨论它们。 像ZooKeeper这样的工具在提供应用程序可以使用的“外包”协议,故障检测和会员服务方面起着重要的作用。使用起来并不容易,但比开发自己的算法要好得多,可以承受第8章讨论的所有问题。如果你发现自己想要做一个可以归结为一致的东西,而且你想要它要容错,那么建议使用类似ZooKeeper的东西。 -尽管如此,并不是每个系统都需要达成共识:例如,无领导者和多领导者复制系统通常不会使用全球共识。这些系统中出现的冲突(参见第171页的“处理冲突”)是不同领导者之间达成共识的结果,但也许没关系:也许我们只需要处理没有线性化的东西,学会更好地工作具有分支和合并版本历史记录的数据。 +尽管如此,并不是每个系统都需要达成共识:例如,无领导者和多领导者复制系统通常不会使用全球共识。这些系统中出现的冲突(参见第171页的“[处理冲突](ch5.md#处理冲突)”)是不同领导者之间达成共识的结果,但也许没关系:也许我们只需要处理没有线性化的东西,学会更好地工作具有分支和合并版本历史记录的数据。 本章引用了大量关于分布式系统理论的研究。虽然理论论文和证明并不总是容易理解,有时也会做出不切实际的假设,但它们对于通知这一领域的实际工作是非常有价值的:它们帮助我们推理什么可以做,不可以做什么,帮助我们找到违反直觉的方法其中分布式系统往往是有缺陷的。如果你有时间,这些参考资料是值得探索的。 -我们在本书第二部分的末尾介绍了复制(第5章),分区(第6章),事务(第7章),分布式系统故障模型(第8章)以及最后的一致性和共识第9章)。现在我们已经奠定了坚实的理论基础,在第三部分我们将再次转向更实用的系统,并讨论如何从异构构建块中构建强大的应用程序。 +我们在本书第二部分的末尾介绍了复制([第5章](ch5.md)),分区([第6章](ch6.md)),事务([第7章](ch7.md)),分布式系统故障模型([第8章](ch8.md))以及最后的一致性和共识([第9章](ch9.md))。现在我们已经奠定了坚实的理论基础,在[第三部分](part-iii.md)我们将再次转向更实用的系统,并讨论如何从异构构建块中构建强大的应用程序。 @@ -1015,326 +1017,175 @@ ZooKeeper和朋友们可以看作是成员服务研究的悠久历史的一部 1. Eric A. Brewer: “[CAP Twelve Years Later: How the 'Rules' Have Changed](http://cs609.cs.ua.edu/CAP12.pdf),” *IEEE Computer Magazine*, volume 45, number 2, pages 23–29, February 2012. [doi:10.1109/MC.2012.37](http://dx.doi.org/10.1109/MC.2012.37) -1. Susan B. Davidson, Hector Garcia-Molina, and Dale Skeen: - “[Consistency in Partitioned Networks](http://delab.csd.auth.gr/~dimitris/courses/mpc_fall05/papers/invalidation/acm_csur85_partitioned_network_consistency.pdf),” *ACM Computing Surveys*, volume 17, number 3, pages 341–370, September 1985. - [doi:10.1145/5505.5508](http://dx.doi.org/10.1145/5505.5508) +1. Susan B. Davidson, Hector Garcia-Molina, and Dale Skeen: “[Consistency in Partitioned Networks](http://delab.csd.auth.gr/~dimitris/courses/mpc_fall05/papers/invalidation/acm_csur85_partitioned_network_consistency.pdf),” *ACM Computing Surveys*, volume 17, number 3, pages 341–370, September 1985. [doi:10.1145/5505.5508](http://dx.doi.org/10.1145/5505.5508) -1. Paul R. Johnson and Robert H. Thomas: - “[RFC 677: The Maintenance of Duplicate Databases](https://tools.ietf.org/html/rfc677),” Network Working Group, January 27, 1975. +1. Paul R. Johnson and Robert H. Thomas: “[RFC 677: The Maintenance of Duplicate Databases](https://tools.ietf.org/html/rfc677),” Network Working Group, January 27, 1975. -1. Bruce G. Lindsay, Patricia Griffiths Selinger, C. Galtieri, et al.: - “[Notes on Distributed Databases](http://domino.research.ibm.com/library/cyberdig.nsf/papers/A776EC17FC2FCE73852579F100578964/$File/RJ2571.pdf),” IBM Research, Research Report RJ2571(33471), July 1979. +1. Bruce G. Lindsay, Patricia Griffiths Selinger, C. Galtieri, et al.: “[Notes on Distributed Databases](http://domino.research.ibm.com/library/cyberdig.nsf/papers/A776EC17FC2FCE73852579F100578964/$File/RJ2571.pdf),” IBM Research, Research Report RJ2571(33471), July 1979. -1. Michael J. Fischer and Alan Michael: - “[Sacrificing Serializability to Attain High Availability of Data in an Unreliable Network](http://www.cs.ucsb.edu/~agrawal/spring2011/ugrad/p70-fischer.pdf),” at - *1st ACM Symposium on Principles of Database Systems* (PODS), March 1982. +1. Michael J. Fischer and Alan Michael: “[Sacrificing Serializability to Attain High Availability of Data in an Unreliable Network](http://www.cs.ucsb.edu/~agrawal/spring2011/ugrad/p70-fischer.pdf),” at *1st ACM Symposium on Principles of Database Systems* (PODS), March 1982. [doi:10.1145/588111.588124](http://dx.doi.org/10.1145/588111.588124) -1. Eric A. Brewer: - “[NoSQL: Past, Present, Future](http://www.infoq.com/presentations/NoSQL-History),” - at *QCon San Francisco*, November 2012. +1. Eric A. Brewer: “[NoSQL: Past, Present, Future](http://www.infoq.com/presentations/NoSQL-History),” at *QCon San Francisco*, November 2012. -1. Henry Robinson: - “[CAP Confusion: Problems with 'Partition Tolerance,'](http://blog.cloudera.com/blog/2010/04/cap-confusion-problems-with-partition-tolerance/)” *blog.cloudera.com*, April 26, 2010. +1. Henry Robinson: “[CAP Confusion: Problems with 'Partition Tolerance,'](http://blog.cloudera.com/blog/2010/04/cap-confusion-problems-with-partition-tolerance/)” *blog.cloudera.com*, April 26, 2010. -1. Adrian Cockcroft: - “[Migrating to Microservices](http://www.infoq.com/presentations/migration-cloud-native),” at *QCon London*, March 2014. +1. Adrian Cockcroft: “[Migrating to Microservices](http://www.infoq.com/presentations/migration-cloud-native),” at *QCon London*, March 2014. -1. Martin Kleppmann: - “[A Critique of the CAP Theorem](http://arxiv.org/abs/1509.05393),” arXiv:1509.05393, - September 17, 2015. +1. Martin Kleppmann: “[A Critique of the CAP Theorem](http://arxiv.org/abs/1509.05393),” arXiv:1509.05393, September 17, 2015. -1. Nancy A. Lynch: - “[A Hundred Impossibility Proofs for Distributed Computing](http://groups.csail.mit.edu/tds/papers/Lynch/podc89.pdf),” at *8th ACM Symposium on Principles of Distributed - Computing* (PODC), August 1989. - [doi:10.1145/72981.72982](http://dx.doi.org/10.1145/72981.72982) +1. Nancy A. Lynch: “[A Hundred Impossibility Proofs for Distributed Computing](http://groups.csail.mit.edu/tds/papers/Lynch/podc89.pdf),” at *8th ACM Symposium on Principles of Distributed Computing* (PODC), August 1989. [doi:10.1145/72981.72982](http://dx.doi.org/10.1145/72981.72982) -1. Hagit Attiya, Faith Ellen, and Adam Morrison: - “[Limitations of Highly-Available Eventually-Consistent Data Stores](http://www.cs.technion.ac.il/people/mad/online-publications/podc2015-replds.pdf),” at *ACM Symposium on Principles of Distributed Computing* (PODC), July 2015. [doi:10.1145/2767386.2767419](http://dx.doi.org/10.1145/2767386.2767419) +1. Hagit Attiya, Faith Ellen, and Adam Morrison: “[Limitations of Highly-Available Eventually-Consistent Data Stores](http://www.cs.technion.ac.il/people/mad/online-publications/podc2015-replds.pdf),” at *ACM Symposium on Principles of Distributed Computing* (PODC), July 2015. doi:10.1145/2767386.2767419](http://dx.doi.org/10.1145/2767386.2767419) -1. Peter Sewell, Susmit Sarkar, - Scott Owens, et al.: - “[x86-TSO: A Rigorous and Usable Programmer's Model for x86 Multiprocessors](http://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf),” *Communications of the ACM*, - volume 53, number 7, pages 89–97, July 2010. +1. Peter Sewell, Susmit Sarkar, Scott Owens, et al.: “[x86-TSO: A Rigorous and Usable Programmer's Model for x86 Multiprocessors](http://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf),” *Communications of the ACM*, volume 53, number 7, pages 89–97, July 2010. [doi:10.1145/1785414.1785443](http://dx.doi.org/10.1145/1785414.1785443) -1. Martin Thompson: - “[Memory Barriers/Fences](http://mechanical-sympathy.blogspot.co.uk/2011/07/memory-barriersfences.html),” *mechanical-sympathy.blogspot.co.uk*, July 24, 2011. +1. Martin Thompson: “[Memory Barriers/Fences](http://mechanical-sympathy.blogspot.co.uk/2011/07/memory-barriersfences.html),” *mechanical-sympathy.blogspot.co.uk*, July 24, 2011. -1. Ulrich Drepper: - “[What Every Programmer Should Know About Memory](http://www.akkadia.org/drepper/cpumemory.pdf),” *akkadia.org*, November 21, 2007. +1. Ulrich Drepper: “[What Every Programmer Should Know About Memory](http://www.akkadia.org/drepper/cpumemory.pdf),” *akkadia.org*, November 21, 2007. -1. Daniel J. Abadi: - “[Consistency Tradeoffs in Modern Distributed Database System Design](http://cs-www.cs.yale.edu/homes/dna/papers/abadi-pacelc.pdf),” *IEEE Computer Magazine*, - volume 45, number 2, pages 37–42, February 2012. - [doi:10.1109/MC.2012.33](http://dx.doi.org/10.1109/MC.2012.33) +1. Daniel J. Abadi: “[Consistency Tradeoffs in Modern Distributed Database System Design](http://cs-www.cs.yale.edu/homes/dna/papers/abadi-pacelc.pdf),” *IEEE Computer Magazine*, volume 45, number 2, pages 37–42, February 2012. [doi:10.1109/MC.2012.33](http://dx.doi.org/10.1109/MC.2012.33) -1. Hagit Attiya and Jennifer L. Welch: - “[Sequential Consistency Versus Linearizability](http://courses.csail.mit.edu/6.852/01/papers/p91-attiya.pdf),” *ACM Transactions on Computer Systems* (TOCS), - volume 12, number 2, pages 91–122, May 1994. - [doi:10.1145/176575.176576](http://dx.doi.org/10.1145/176575.176576) +1. Hagit Attiya and Jennifer L. Welch: “[Sequential Consistency Versus Linearizability](http://courses.csail.mit.edu/6.852/01/papers/p91-attiya.pdf),” *ACM Transactions on Computer Systems* (TOCS), volume 12, number 2, pages 91–122, May 1994. [doi:10.1145/176575.176576](http://dx.doi.org/10.1145/176575.176576) -1. Mustaque Ahamad, Gil Neiger, James E. Burns, et al.: - “[Causal Memory: Definitions, Implementation, and Programming](http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Seminar_MCMM11/Causal_memory_1996.pdf),” *Distributed - Computing*, volume 9, number 1, pages 37–49, March 1995. - [doi:10.1007/BF01784241](http://dx.doi.org/10.1007/BF01784241) +1. Mustaque Ahamad, Gil Neiger, James E. Burns, et al.: “[Causal Memory: Definitions, Implementation, and Programming](http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Seminar_MCMM11/Causal_memory_1996.pdf),” *Distributed Computing*, volume 9, number 1, pages 37–49, March 1995. [doi:10.1007/BF01784241](http://dx.doi.org/10.1007/BF01784241) -1. Wyatt Lloyd, Michael J. Freedman, - Michael Kaminsky, and David G. Andersen: - “[Stronger Semantics for Low-Latency Geo-Replicated Storage](https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final149.pdf),” at *10th USENIX Symposium on Networked - Systems Design and Implementation* (NSDI), April 2013. +1. Wyatt Lloyd, Michael J. Freedman, Michael Kaminsky, and David G. Andersen: “[Stronger Semantics for Low-Latency Geo-Replicated Storage](https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final149.pdf),” at *10th USENIX Symposium on Networked Systems Design and Implementation* (NSDI), April 2013. -1. Marek Zawirski, Annette Bieniusa, Valter Balegas, et al.: - “[SwiftCloud: Fault-Tolerant Geo-Replication Integrated All the Way to the Client Machine](http://arxiv.org/abs/1310.3107),” INRIA Research Report 8347, August 2013. +1. Marek Zawirski, Annette Bieniusa, Valter Balegas, et al.: “[SwiftCloud: Fault-Tolerant Geo-Replication Integrated All the Way to the Client Machine](http://arxiv.org/abs/1310.3107),” INRIA Research Report 8347, August 2013. -1. Peter Bailis, Ali Ghodsi, Joseph M Hellerstein, and Ion Stoica: - “[Bolt-on Causal Consistency](http://db.cs.berkeley.edu/papers/sigmod13-bolton.pdf),” at +1. Peter Bailis, Ali Ghodsi, Joseph M Hellerstein, and Ion Stoica: “[Bolt-on Causal Consistency](http://db.cs.berkeley.edu/papers/sigmod13-bolton.pdf),” at *ACM International Conference on Management of Data* (SIGMOD), June 2013. -1. Philippe Ajoux, Nathan Bronson, Sanjeev - Kumar, et al.: - “[Challenges to Adopting Stronger Consistency at Scale](https://www.usenix.org/system/files/conference/hotos15/hotos15-paper-ajoux.pdf),” at *15th USENIX Workshop on Hot Topics in - Operating Systems* (HotOS), May 2015. +1. Philippe Ajoux, Nathan Bronson, Sanjeev Kumar, et al.: “[Challenges to Adopting Stronger Consistency at Scale](https://www.usenix.org/system/files/conference/hotos15/hotos15-paper-ajoux.pdf),” at *15th USENIX Workshop on Hot Topics in Operating Systems* (HotOS), May 2015. -1. Peter Bailis: - “[Causality Is Expensive (and What to Do About It)](http://www.bailis.org/blog/causality-is-expensive-and-what-to-do-about-it/),” *bailis.org*, February 5, 2014. +1. Peter Bailis: “[Causality Is Expensive (and What to Do About It)](http://www.bailis.org/blog/causality-is-expensive-and-what-to-do-about-it/),” *bailis.org*, February 5, 2014. -1. Ricardo Gonçalves, Paulo Sérgio Almeida, - Carlos Baquero, and Victor Fonte: - “[Concise Server-Wide Causality Management for Eventually Consistent Data Stores](http://haslab.uminho.pt/tome/files/global_logical_clocks.pdf),” at *15th IFIP International - Conference on Distributed Applications and Interoperable Systems* (DAIS), June 2015. - [doi:10.1007/978-3-319-19129-4_6](http://dx.doi.org/10.1007/978-3-319-19129-4_6) +1. Ricardo Gonçalves, Paulo Sérgio Almeida, Carlos Baquero, and Victor Fonte: “[Concise Server-Wide Causality Management for Eventually Consistent Data Stores](http://haslab.uminho.pt/tome/files/global_logical_clocks.pdf),” at *15th IFIP International Conference on Distributed Applications and Interoperable Systems* (DAIS), June 2015. [doi:10.1007/978-3-319-19129-4_6](http://dx.doi.org/10.1007/978-3-319-19129-4_6) -1. Rob Conery: - “[A Better ID Generator for PostgreSQL](http://rob.conery.io/2014/05/29/a-better-id-generator-for-postgresql/),” *rob.conery.io*, May 29, 2014. +1. Rob Conery: “[A Better ID Generator for PostgreSQL](http://rob.conery.io/2014/05/29/a-better-id-generator-for-postgresql/),” *rob.conery.io*, May 29, 2014. -1. Leslie Lamport: - “[Time, Clocks, and the Ordering of Events in a Distributed System](http://research.microsoft.com/en-US/um/people/Lamport/pubs/time-clocks.pdf),” *Communications of the ACM*, - volume 21, number 7, pages 558–565, July 1978. - [doi:10.1145/359545.359563](http://dx.doi.org/10.1145/359545.359563) +1. Leslie Lamport: “[Time, Clocks, and the Ordering of Events in a Distributed System](http://research.microsoft.com/en-US/um/people/Lamport/pubs/time-clocks.pdf),” *Communications of the ACM*, volume 21, number 7, pages 558–565, July 1978. [doi:10.1145/359545.359563](http://dx.doi.org/10.1145/359545.359563) -1. Xavier Défago, André Schiper, and Péter Urbán: - “[Total Order Broadcast and Multicast Algorithms: Taxonomy and Survey](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4883/1/defago_et_al.pdf),” *ACM Computing - Surveys*, volume 36, number 4, pages 372–421, December 2004. +1. Xavier Défago, André Schiper, and Péter Urbán: “[Total Order Broadcast and Multicast Algorithms: Taxonomy and Survey](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4883/1/defago_et_al.pdf),” *ACM Computing Surveys*, volume 36, number 4, pages 372–421, December 2004. [doi:10.1145/1041680.1041682](http://dx.doi.org/10.1145/1041680.1041682) -1. Hagit Attiya and Jennifer Welch: *Distributed - Computing: Fundamentals, Simulations and Advanced Topics*, 2nd edition. - John Wiley & Sons, 2004. ISBN: 978-0-471-45324-6, - [doi:10.1002/0471478210](http://dx.doi.org/10.1002/0471478210) +1. Hagit Attiya and Jennifer Welch: *Distributed Computing: Fundamentals, Simulations and Advanced Topics*, 2nd edition. John Wiley & Sons, 2004. ISBN: 978-0-471-45324-6, [doi:10.1002/0471478210](http://dx.doi.org/10.1002/0471478210) -1. Mahesh - Balakrishnan, Dahlia Malkhi, Vijayan Prabhakaran, et al.: - “[CORFU: A Shared Log Design for Flash Clusters](https://www.usenix.org/system/files/conference/nsdi12/nsdi12-final30.pdf),” at *9th USENIX Symposium on Networked - Systems Design and Implementation* (NSDI), April 2012. +1. Mahesh Balakrishnan, Dahlia Malkhi, Vijayan Prabhakaran, et al.: “[CORFU: A Shared Log Design for Flash Clusters](https://www.usenix.org/system/files/conference/nsdi12/nsdi12-final30.pdf),” at *9th USENIX Symposium on Networked Systems Design and Implementation* (NSDI), April 2012. -1. Fred B. Schneider: - “[Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial](http://www.cs.cornell.edu/fbs/publications/smsurvey.pdf),” *ACM Computing Surveys*, volume - 22, number 4, pages 299–319, December 1990. +1. Fred B. Schneider: “[Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial](http://www.cs.cornell.edu/fbs/publications/smsurvey.pdf),” *ACM Computing Surveys*, volume 22, number 4, pages 299–319, December 1990. -1. Alexander Thomson, Thaddeus Diamond, Shu-Chun Weng, et al.: - “[Calvin: Fast Distributed Transactions for Partitioned Database Systems](http://cs.yale.edu/homes/thomson/publications/calvin-sigmod12.pdf),” at *ACM International Conference - on Management of Data* (SIGMOD), May 2012. +1. Alexander Thomson, Thaddeus Diamond, Shu-Chun Weng, et al.: “[Calvin: Fast Distributed Transactions for Partitioned Database Systems](http://cs.yale.edu/homes/thomson/publications/calvin-sigmod12.pdf),” at *ACM International Conference on Management of Data* (SIGMOD), May 2012. -1. Mahesh Balakrishnan, Dahlia Malkhi, Ted Wobber, et al.: - “[Tango: Distributed Data Structures over a Shared Log](http://research.microsoft.com/pubs/199947/Tango.pdf),” at *24th ACM Symposium on Operating Systems - Principles* (SOSP), November 2013. +1. Mahesh Balakrishnan, Dahlia Malkhi, Ted Wobber, et al.: “[Tango: Distributed Data Structures over a Shared Log](http://research.microsoft.com/pubs/199947/Tango.pdf),” at *24th ACM Symposium on Operating Systems Principles* (SOSP), November 2013. [doi:10.1145/2517349.2522732](http://dx.doi.org/10.1145/2517349.2522732) -1. Robbert van Renesse and Fred B. Schneider: - “[Chain Replication for Supporting High Throughput and Availability](http://static.usenix.org/legacy/events/osdi04/tech/full_papers/renesse/renesse.pdf),” at *6th USENIX - Symposium on Operating System Design and Implementation* (OSDI), December 2004. +1. Robbert van Renesse and Fred B. Schneider: “[Chain Replication for Supporting High Throughput and Availability](http://static.usenix.org/legacy/events/osdi04/tech/full_papers/renesse/renesse.pdf),” at *6th USENIX Symposium on Operating System Design and Implementation* (OSDI), December 2004. -1. Leslie Lamport: - “[How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs](http://research-srv.microsoft.com/en-us/um/people/lamport/pubs/multi.pdf),” *IEEE - Transactions on Computers*, volume 28, number 9, pages 690–691, September 1979. +1. Leslie Lamport: “[How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs](http://research-srv.microsoft.com/en-us/um/people/lamport/pubs/multi.pdf),” *IEEE Transactions on Computers*, volume 28, number 9, pages 690–691, September 1979. [doi:10.1109/TC.1979.1675439](http://dx.doi.org/10.1109/TC.1979.1675439) -1. Enis Söztutar, Devaraj Das, and Carter Shanklin: - “[Apache HBase High Availability at the Next Level](http://hortonworks.com/blog/apache-hbase-high-availability-next-level/),” *hortonworks.com*, January 22, 2015. +1. Enis Söztutar, Devaraj Das, and Carter Shanklin: “[Apache HBase High Availability at the Next Level](http://hortonworks.com/blog/apache-hbase-high-availability-next-level/),” *hortonworks.com*, January 22, 2015. -1. Brian F Cooper, Raghu Ramakrishnan, Utkarsh Srivastava, et al.: - “[PNUTS: Yahoo!’s Hosted Data Serving Platform](http://www.mpi-sws.org/~druschel/courses/ds/papers/cooper-pnuts.pdf),” at *34th International Conference on Very Large Data - Bases* (VLDB), August 2008. +1. Brian F Cooper, Raghu Ramakrishnan, Utkarsh Srivastava, et al.: “[PNUTS: Yahoo!’s Hosted Data Serving Platform](http://www.mpi-sws.org/~druschel/courses/ds/papers/cooper-pnuts.pdf),” at *34th International Conference on Very Large Data Bases* (VLDB), August 2008. [doi:10.14778/1454159.1454167](http://dx.doi.org/10.14778/1454159.1454167) -1. Tushar Deepak Chandra and Sam Toueg: - “[Unreliable Failure Detectors for Reliable Distributed Systems](http://courses.csail.mit.edu/6.852/08/papers/CT96-JACM.pdf),” *Journal of the ACM*, - volume 43, number 2, pages 225–267, March 1996. - [doi:10.1145/226643.226647](http://dx.doi.org/10.1145/226643.226647) +1. Tushar Deepak Chandra and Sam Toueg: “[Unreliable Failure Detectors for Reliable Distributed Systems](http://courses.csail.mit.edu/6.852/08/papers/CT96-JACM.pdf),” *Journal of the ACM*, volume 43, number 2, pages 225–267, March 1996. [doi:10.1145/226643.226647](http://dx.doi.org/10.1145/226643.226647) -1. Michael J. Fischer, Nancy Lynch, and Michael S. Paterson: - “[Impossibility of Distributed Consensus with One Faulty Process](https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf),” *Journal of the ACM*, volume 32, number 2, pages 374–382, April 1985. - [doi:10.1145/3149.214121](http://dx.doi.org/10.1145/3149.214121) +1. Michael J. Fischer, Nancy Lynch, and Michael S. Paterson: “[Impossibility of Distributed Consensus with One Faulty Process](https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf),” *Journal of the ACM*, volume 32, number 2, pages 374–382, April 1985. [doi:10.1145/3149.214121](http://dx.doi.org/10.1145/3149.214121) -1. Michael Ben-Or: “Another Advantage of Free - Choice: Completely Asynchronous Agreement Protocols,” at *2nd ACM Symposium on Principles of - Distributed Computing* (PODC), August 1983. - [doi:10.1145/800221.806707](http://dl.acm.org/citation.cfm?id=806707) +1. Michael Ben-Or: “Another Advantage of Free Choice: Completely Asynchronous Agreement Protocols,” at *2nd ACM Symposium on Principles of Distributed Computing* (PODC), August 1983. [doi:10.1145/800221.806707](http://dl.acm.org/citation.cfm?id=806707) -1. Jim N. Gray and Leslie Lamport: - “[Consensus on Transaction Commit](http://db.cs.berkeley.edu/cs286/papers/paxoscommit-tods2006.pdf),” *ACM Transactions on Database Systems* (TODS), volume 31, - number 1, pages 133–160, March 2006. - [doi:10.1145/1132863.1132867](http://dx.doi.org/10.1145/1132863.1132867) +1. Jim N. Gray and Leslie Lamport: “[Consensus on Transaction Commit](http://db.cs.berkeley.edu/cs286/papers/paxoscommit-tods2006.pdf),” *ACM Transactions on Database Systems* (TODS), volume 31, number 1, pages 133–160, March 2006. [doi:10.1145/1132863.1132867](http://dx.doi.org/10.1145/1132863.1132867) -1. Rachid Guerraoui: - “[Revisiting the Relationship Between Non-Blocking Atomic Commitment and Consensus](https://pdfs.semanticscholar.org/5d06/489503b6f791aa56d2d7942359c2592e44b0.pdf),” at *9th International - Workshop on Distributed Algorithms* (WDAG), September 1995. - [doi:10.1007/BFb0022140](http://dx.doi.org/10.1007/BFb0022140) +1. Rachid Guerraoui: “[Revisiting the Relationship Between Non-Blocking Atomic Commitment and Consensus](https://pdfs.semanticscholar.org/5d06/489503b6f791aa56d2d7942359c2592e44b0.pdf),” at *9th International Workshop on Distributed Algorithms* (WDAG), September 1995. [doi:10.1007/BFb0022140](http://dx.doi.org/10.1007/BFb0022140) -1. Thanumalayan Sankaranarayana Pillai, Vijay Chidambaram, - Ramnatthan Alagappan, et al.: “[All File Systems Are Not Created Equal: On the Complexity of Crafting Crash-Consistent Applications](http://research.cs.wisc.edu/wind/Publications/alice-osdi14.pdf),” +1. Thanumalayan Sankaranarayana Pillai, Vijay Chidambaram, Ramnatthan Alagappan, et al.: “[All File Systems Are Not Created Equal: On the Complexity of Crafting Crash-Consistent Applications](http://research.cs.wisc.edu/wind/Publications/alice-osdi14.pdf),” at *11th USENIX Symposium on Operating Systems Design and Implementation* (OSDI), October 2014. -1. Jim Gray: - “[The Transaction Concept: Virtues and Limitations](http://research.microsoft.com/en-us/um/people/gray/papers/theTransactionConcept.pdf),” at *7th International Conference on - Very Large Data Bases* (VLDB), September 1981. +1. Jim Gray: “[The Transaction Concept: Virtues and Limitations](http://research.microsoft.com/en-us/um/people/gray/papers/theTransactionConcept.pdf),” at *7th International Conference on Very Large Data Bases* (VLDB), September 1981. -1. Hector Garcia-Molina and Kenneth Salem: - “[Sagas](http://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf),” at - *ACM International Conference on Management of Data* (SIGMOD), May 1987. - [doi:10.1145/38713.38742](http://dx.doi.org/10.1145/38713.38742) +1. Hector Garcia-Molina and Kenneth Salem: “[Sagas](http://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf),” at *ACM International Conference on Management of Data* (SIGMOD), May 1987. [doi:10.1145/38713.38742](http://dx.doi.org/10.1145/38713.38742) -1. C. Mohan, Bruce G. Lindsay, and Ron Obermarck: - “[Transaction Management in the R* Distributed Database Management System](https://cs.brown.edu/courses/csci2270/archives/2012/papers/dtxn/p378-mohan.pdf),” - *ACM Transactions on Database Systems*, volume 11, number 4, pages 378–396, December 1986. - [doi:10.1145/7239.7266](http://dx.doi.org/10.1145/7239.7266) +1. C. Mohan, Bruce G. Lindsay, and Ron Obermarck: “[Transaction Management in the R* Distributed Database Management System](https://cs.brown.edu/courses/csci2270/archives/2012/papers/dtxn/p378-mohan.pdf),” *ACM Transactions on Database Systems*, volume 11, number 4, pages 378–396, December 1986. [doi:10.1145/7239.7266](http://dx.doi.org/10.1145/7239.7266) 1. “[Distributed Transaction Processing: The XA Specification](http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf),” X/Open Company Ltd., Technical Standard XO/CAE/91/300, December 1991. ISBN: 978-1-872-63024-3 -1. Mike Spille: - “[XA Exposed, Part II](http://www.jroller.com/pyrasun/entry/xa_exposed_part_ii_schwartz),” - *jroller.com*, April 3, 2004. +1. Mike Spille: “[XA Exposed, Part II](http://www.jroller.com/pyrasun/entry/xa_exposed_part_ii_schwartz),” *jroller.com*, April 3, 2004. -1. Ivan Silva Neto and Francisco Reverbel: - “[Lessons Learned from Implementing WS-Coordination and WS-AtomicTransaction](http://www.ime.usp.br/~reverbel/papers/icis2008.pdf),” at *7th IEEE/ACIS International Conference on - Computer and Information Science* (ICIS), May 2008. - [doi:10.1109/ICIS.2008.75](http://dx.doi.org/10.1109/ICIS.2008.75) +1. Ivan Silva Neto and Francisco Reverbel: “[Lessons Learned from Implementing WS-Coordination and WS-AtomicTransaction](http://www.ime.usp.br/~reverbel/papers/icis2008.pdf),” at *7th IEEE/ACIS International Conference on Computer and Information Science* (ICIS), May 2008. [doi:10.1109/ICIS.2008.75](http://dx.doi.org/10.1109/ICIS.2008.75) -1. James E. Johnson, David E. Langworthy, Leslie Lamport, - and Friedrich H. Vogt: - “[Formal Specification of a Web Services Protocol](http://research.microsoft.com/en-us/um/people/lamport/pubs/wsfm-web.pdf),” at *1st International Workshop on Web Services and - Formal Methods* (WS-FM), February 2004. - [doi:10.1016/j.entcs.2004.02.022](http://dx.doi.org/10.1016/j.entcs.2004.02.022) +1. James E. Johnson, David E. Langworthy, Leslie Lamport, and Friedrich H. Vogt: “[Formal Specification of a Web Services Protocol](http://research.microsoft.com/en-us/um/people/lamport/pubs/wsfm-web.pdf),” at *1st International Workshop on Web Services and Formal Methods* (WS-FM), February 2004. [doi:10.1016/j.entcs.2004.02.022](http://dx.doi.org/10.1016/j.entcs.2004.02.022) -1. Dale Skeen: - “[Nonblocking Commit Protocols](http://www.cs.utexas.edu/~lorenzo/corsi/cs380d/papers/Ske81.pdf),” at *ACM International Conference on Management of Data* (SIGMOD), April 1981. - [doi:10.1145/582318.582339](http://dx.doi.org/10.1145/582318.582339) +1. Dale Skeen: “[Nonblocking Commit Protocols](http://www.cs.utexas.edu/~lorenzo/corsi/cs380d/papers/Ske81.pdf),” at *ACM International Conference on Management of Data* (SIGMOD), April 1981. [doi:10.1145/582318.582339](http://dx.doi.org/10.1145/582318.582339) -1. Gregor Hohpe: - “[Your Coffee Shop Doesn’t Use Two-Phase Commit](http://www.martinfowler.com/ieeeSoftware/coffeeShop.pdf),” *IEEE Software*, volume 22, number 2, pages 64–66, March 2005. - [doi:10.1109/MS.2005.52](http://dx.doi.org/10.1109/MS.2005.52) +1. Gregor Hohpe: “[Your Coffee Shop Doesn’t Use Two-Phase Commit](http://www.martinfowler.com/ieeeSoftware/coffeeShop.pdf),” *IEEE Software*, volume 22, number 2, pages 64–66, March 2005. [doi:10.1109/MS.2005.52](http://dx.doi.org/10.1109/MS.2005.52) -1. Pat Helland: - “[Life Beyond Distributed Transactions: An Apostate’s Opinion](http://www-db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf),” at *3rd Biennial Conference on Innovative Data Systems - Research* (CIDR), January 2007. +1. Pat Helland: “[Life Beyond Distributed Transactions: An Apostate’s Opinion](http://www-db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf),” at *3rd Biennial Conference on Innovative Data Systems Research* (CIDR), January 2007. -1. Jonathan Oliver: - “[My Beef with MSDTC and Two-Phase Commits](http://blog.jonathanoliver.com/my-beef-with-msdtc-and-two-phase-commits/),” *blog.jonathanoliver.com*, April 4, 2011. +1. Jonathan Oliver: “[My Beef with MSDTC and Two-Phase Commits](http://blog.jonathanoliver.com/my-beef-with-msdtc-and-two-phase-commits/),” *blog.jonathanoliver.com*, April 4, 2011. -1. Oren Eini (Ahende Rahien): - “[The Fallacy of Distributed Transactions](http://ayende.com/blog/167362/the-fallacy-of-distributed-transactions),” *ayende.com*, July 17, 2014. +1. Oren Eini (Ahende Rahien): “[The Fallacy of Distributed Transactions](http://ayende.com/blog/167362/the-fallacy-of-distributed-transactions),” *ayende.com*, July 17, 2014. -1. Clemens Vasters: - “[Transactions in Windows Azure (with Service Bus) – An Email Discussion](https://blogs.msdn.microsoft.com/clemensv/2012/07/30/transactions-in-windows-azure-with-service-bus-an-email-discussion/),” *vasters.com*, July 30, 2012. +1. Clemens Vasters: “[Transactions in Windows Azure (with Service Bus) – An Email Discussion](https://blogs.msdn.microsoft.com/clemensv/2012/07/30/transactions-in-windows-azure-with-service-bus-an-email-discussion/),” *vasters.com*, July 30, 2012. 1. “[Understanding Transactionality in Azure](https://docs.particular.net/nservicebus/azure/understanding-transactionality-in-azure),” NServiceBus Documentation, Particular Software, 2015. -1. Randy Wigginton, Ryan Lowe, - Marcos Albe, and Fernando Ipar: - “[Distributed Transactions in MySQL](https://www.percona.com/live/mysql-conference-2013/sites/default/files/slides/XA_final.pdf),” at *MySQL Conference and Expo*, April 2013. +1. Randy Wigginton, Ryan Lowe, Marcos Albe, and Fernando Ipar: “[Distributed Transactions in MySQL](https://www.percona.com/live/mysql-conference-2013/sites/default/files/slides/XA_final.pdf),” at *MySQL Conference and Expo*, April 2013. -1. Mike Spille: - “[XA Exposed, Part I](http://www.jroller.com/pyrasun/entry/xa_exposed),” - *jroller.com*, April 3, 2004. +1. Mike Spille: “[XA Exposed, Part I](http://www.jroller.com/pyrasun/entry/xa_exposed),” *jroller.com*, April 3, 2004. -1. Ajmer Dhariwal: - “[Orphaned MSDTC Transactions (-2 spids)](http://www.eraofdata.com/orphaned-msdtc-transactions-2-spids/),” *eraofdata.com*, December 12, 2008. +1. Ajmer Dhariwal: “[Orphaned MSDTC Transactions (-2 spids)](http://www.eraofdata.com/orphaned-msdtc-transactions-2-spids/),” *eraofdata.com*, December 12, 2008. -1. Paul Randal: - “[Real World Story of DBCC PAGE Saving the Day](http://www.sqlskills.com/blogs/paul/real-world-story-of-dbcc-page-saving-the-day/),” *sqlskills.com*, June 19, 2013. +1. Paul Randal: “[Real World Story of DBCC PAGE Saving the Day](http://www.sqlskills.com/blogs/paul/real-world-story-of-dbcc-page-saving-the-day/),” *sqlskills.com*, June 19, 2013. 1. “[in-doubt xact resolution Server Configuration Option](https://msdn.microsoft.com/en-us/library/ms179586.aspx),” SQL Server 2016 documentation, Microsoft, Inc., 2016. -1. Cynthia Dwork, Nancy Lynch, and Larry Stockmeyer: - “[Consensus in the Presence of Partial Synchrony](http://www.net.t-labs.tu-berlin.de/~petr/ADC-07/papers/DLS88.pdf),” *Journal of the ACM*, volume 35, number 2, pages 288–323, - April 1988. [doi:10.1145/42282.42283](http://dx.doi.org/10.1145/42282.42283) +1. Cynthia Dwork, Nancy Lynch, and Larry Stockmeyer: “[Consensus in the Presence of Partial Synchrony](http://www.net.t-labs.tu-berlin.de/~petr/ADC-07/papers/DLS88.pdf),” *Journal of the ACM*, volume 35, number 2, pages 288–323, April 1988. [doi:10.1145/42282.42283](http://dx.doi.org/10.1145/42282.42283) -1. Miguel Castro and Barbara H. Liskov: - “[Practical Byzantine Fault Tolerance and Proactive Recovery](http://zoo.cs.yale.edu/classes/cs426/2012/bib/castro02practical.pdf),” *ACM Transactions on Computer Systems*, - volume 20, number 4, pages 396–461, November 2002. - [doi:10.1145/571637.571640](http://dx.doi.org/10.1145/571637.571640) +1. Miguel Castro and Barbara H. Liskov: “[Practical Byzantine Fault Tolerance and Proactive Recovery](http://zoo.cs.yale.edu/classes/cs426/2012/bib/castro02practical.pdf),” *ACM Transactions on Computer Systems*, volume 20, number 4, pages 396–461, November 2002. [doi:10.1145/571637.571640](http://dx.doi.org/10.1145/571637.571640) -1. Brian M. Oki and Barbara H. Liskov: - “[Viewstamped Replication: A New Primary Copy Method to Support Highly-Available Distributed Systems](http://www.cs.princeton.edu/courses/archive/fall11/cos518/papers/viewstamped.pdf),” at - *7th ACM Symposium on Principles of Distributed Computing* (PODC), August 1988. - [doi:10.1145/62546.62549](http://dx.doi.org/10.1145/62546.62549) +1. Brian M. Oki and Barbara H. Liskov: “[Viewstamped Replication: A New Primary Copy Method to Support Highly-Available Distributed Systems](http://www.cs.princeton.edu/courses/archive/fall11/cos518/papers/viewstamped.pdf),” at *7th ACM Symposium on Principles of Distributed Computing* (PODC), August 1988. [doi:10.1145/62546.62549](http://dx.doi.org/10.1145/62546.62549) -1. Barbara H. Liskov and James Cowling: - “[Viewstamped Replication Revisited](http://pmg.csail.mit.edu/papers/vr-revisited.pdf),” - Massachusetts Institute of Technology, Tech Report MIT-CSAIL-TR-2012-021, July 2012. +1. Barbara H. Liskov and James Cowling: “[Viewstamped Replication Revisited](http://pmg.csail.mit.edu/papers/vr-revisited.pdf),” Massachusetts Institute of Technology, Tech Report MIT-CSAIL-TR-2012-021, July 2012. -1. Leslie Lamport: - “[The Part-Time Parliament](http://research.microsoft.com/en-us/um/people/lamport/pubs/lamport-paxos.pdf),” *ACM Transactions on Computer Systems*, volume 16, number 2, - pages 133–169, May 1998. - [doi:10.1145/279227.279229](http://dx.doi.org/10.1145/279227.279229) +1. Leslie Lamport: “[The Part-Time Parliament](http://research.microsoft.com/en-us/um/people/lamport/pubs/lamport-paxos.pdf),” *ACM Transactions on Computer Systems*, volume 16, number 2, pages 133–169, May 1998. [doi:10.1145/279227.279229](http://dx.doi.org/10.1145/279227.279229) -1. Leslie Lamport: - “[Paxos Made Simple](http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf),” *ACM SIGACT News*, volume 32, number 4, pages 51–58, December 2001. +1. Leslie Lamport: “[Paxos Made Simple](http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf),” *ACM SIGACT News*, volume 32, number 4, pages 51–58, December 2001. -1. Tushar Deepak Chandra, Robert Griesemer, and Joshua - Redstone: “[Paxos Made Live – An Engineering Perspective](http://www.read.seas.harvard.edu/~kohler/class/08w-dsi/chandra07paxos.pdf),” at *26th ACM Symposium on Principles of Distributed - Computing* (PODC), June 2007. +1. Tushar Deepak Chandra, Robert Griesemer, and Joshua Redstone: “[Paxos Made Live – An Engineering Perspective](http://www.read.seas.harvard.edu/~kohler/class/08w-dsi/chandra07paxos.pdf),” at *26th ACM Symposium on Principles of Distributed Computing* (PODC), June 2007. -1. Robbert - van Renesse: “[Paxos Made Moderately Complex](http://www.cs.cornell.edu/home/rvr/Paxos/paxos.pdf),” *cs.cornell.edu*, March 2011. +1. Robbert van Renesse: “[Paxos Made Moderately Complex](http://www.cs.cornell.edu/home/rvr/Paxos/paxos.pdf),” *cs.cornell.edu*, March 2011. -1. Diego Ongaro: - “[Consensus: Bridging Theory and Practice](https://github.com/ongardie/dissertation),” - PhD Thesis, Stanford University, August 2014. +1. Diego Ongaro: “[Consensus: Bridging Theory and Practice](https://github.com/ongardie/dissertation),” PhD Thesis, Stanford University, August 2014. -1. Heidi Howard, Malte Schwarzkopf, Anil Madhavapeddy, - and Jon Crowcroft: “[Raft Refloated: Do We Have Consensus?](http://www.cl.cam.ac.uk/~ms705/pub/papers/2015-osr-raft.pdf),” *ACM SIGOPS Operating Systems Review*, volume 49, - number 1, pages 12–21, January 2015. +1. Heidi Howard, Malte Schwarzkopf, Anil Madhavapeddy, and Jon Crowcroft: “[Raft Refloated: Do We Have Consensus?](http://www.cl.cam.ac.uk/~ms705/pub/papers/2015-osr-raft.pdf),” *ACM SIGOPS Operating Systems Review*, volume 49, number 1, pages 12–21, January 2015. [doi:10.1145/2723872.2723876](http://dx.doi.org/10.1145/2723872.2723876) -1. André Medeiros: - “[ZooKeeper’s Atomic Broadcast Protocol: Theory and Practice](http://www.tcs.hut.fi/Studies/T-79.5001/reports/2012-deSouzaMedeiros.pdf),” Aalto University School of Science, March 20, 2012. +1. André Medeiros: “[ZooKeeper’s Atomic Broadcast Protocol: Theory and Practice](http://www.tcs.hut.fi/Studies/T-79.5001/reports/2012-deSouzaMedeiros.pdf),” Aalto University School of Science, March 20, 2012. -1. Robbert van Renesse, Nicolas Schiper, and - Fred B. Schneider: “[Vive La Différence: Paxos vs. Viewstamped Replication vs. Zab](http://arxiv.org/abs/1309.5671),” *IEEE Transactions on Dependable and Secure Computing*, - volume 12, number 4, pages 472–484, September 2014. - [doi:10.1109/TDSC.2014.2355848](http://dx.doi.org/10.1109/TDSC.2014.2355848) +1. Robbert van Renesse, Nicolas Schiper, and Fred B. Schneider: “[Vive La Différence: Paxos vs. Viewstamped Replication vs. Zab](http://arxiv.org/abs/1309.5671),” *IEEE Transactions on Dependable and Secure Computing*, + volume 12, number 4, pages 472–484, September 2014. [doi:10.1109/TDSC.2014.2355848](http://dx.doi.org/10.1109/TDSC.2014.2355848) -1. Will - Portnoy: “[Lessons Learned from Implementing Paxos](http://blog.willportnoy.com/2012/06/lessons-learned-from-paxos.html),” *blog.willportnoy.com*, June 14, 2012. +1. Will Portnoy: “[Lessons Learned from Implementing Paxos](http://blog.willportnoy.com/2012/06/lessons-learned-from-paxos.html),” *blog.willportnoy.com*, June 14, 2012. -1. Heidi Howard, Dahlia Malkhi, and Alexander Spiegelman: - “[Flexible Paxos: Quorum Intersection Revisited](https://arxiv.org/abs/1608.06696),” - *arXiv:1608.06696*, August 24, 2016. +1. Heidi Howard, Dahlia Malkhi, and Alexander Spiegelman: “[Flexible Paxos: Quorum Intersection Revisited](https://arxiv.org/abs/1608.06696),” *arXiv:1608.06696*, August 24, 2016. -1. Heidi Howard and Jon Crowcroft: - “[Coracle: Evaluating Consensus at the Internet Edge](http://www.sigcomm.org/sites/default/files/ccr/papers/2015/August/2829988-2790010.pdf),” at *Annual Conference of the ACM Special Interest - Group on Data Communication* (SIGCOMM), August 2015. +1. Heidi Howard and Jon Crowcroft: “[Coracle: Evaluating Consensus at the Internet Edge](http://www.sigcomm.org/sites/default/files/ccr/papers/2015/August/2829988-2790010.pdf),” at *Annual Conference of the ACM Special Interest Group on Data Communication* (SIGCOMM), August 2015. [doi:10.1145/2829988.2790010](http://dx.doi.org/10.1145/2829988.2790010) -1. Kyle Kingsbury: - “[Call Me Maybe: Elasticsearch 1.5.0](https://aphyr.com/posts/323-call-me-maybe-elasticsearch-1-5-0),” *aphyr.com*, April 27, 2015. +1. Kyle Kingsbury: “[Call Me Maybe: Elasticsearch 1.5.0](https://aphyr.com/posts/323-call-me-maybe-elasticsearch-1-5-0),” *aphyr.com*, April 27, 2015. -1. Ivan Kelly: - “[BookKeeper Tutorial](https://github.com/ivankelly/bookkeeper-tutorial),” - *github.com*, October 2014. +1. Ivan Kelly: “[BookKeeper Tutorial](https://github.com/ivankelly/bookkeeper-tutorial),” *github.com*, October 2014. -1. Camille Fournier: - “[Consensus Systems for the Skeptical Architect](http://www.ustream.tv/recorded/61483409),” at *Craft Conference*, Budapest, Hungary, April 2015. +1. Camille Fournier: “[Consensus Systems for the Skeptical Architect](http://www.ustream.tv/recorded/61483409),” at *Craft Conference*, Budapest, Hungary, April 2015. -1. Kenneth P. Birman: - “[A History of the Virtual Synchrony Replication Model](https://www.truststc.org/pubs/713.html),” in *Replication: Theory and Practice*, Springer LNCS volume 5959, chapter 6, - pages 91–120, 2010. ISBN: 978-3-642-11293-5, - [doi:10.1007/978-3-642-11294-2_6](http://dx.doi.org/10.1007/978-3-642-11294-2_6) +1. Kenneth P. Birman: “[A History of the Virtual Synchrony Replication Model](https://www.truststc.org/pubs/713.html),” in *Replication: Theory and Practice*, Springer LNCS volume 5959, chapter 6, pages 91–120, 2010. ISBN: 978-3-642-11293-5, [doi:10.1007/978-3-642-11294-2_6](http://dx.doi.org/10.1007/978-3-642-11294-2_6)