基本概念 部分失效资料来源《分布式系统原理与范型》第2版,极客时间《分布式技术原理与算法解析》
分布式系统区别于单机系统的一个特性是它可以容许部分失效。当分布式系统中的一个组件发生故障时就可能产生部分失效。这个故障也许会影响到其他组件的正确操作,但同时也有可能完全不影响其他组件。而非分布式系统中的故障通常会影响到所有的组件,可能很容易就使整个应用程序崩溃。
容错性设计目标分布式系统设计中的一个重要日标是以这样的方式来构造系统:它可以从部分失效中自动恢复,而且不会严重地影响整体性能。特别是,当故障发生时,分布式系统应该在进行恢复的同时继续以可接受的方式进行操作,也就是说,它应该能容许错误,在发生错误时某种程度上仍可以继续操作。
容错性设计- 进程恢复与可靠多播;
- 分布式提交协议;
- 故障恢复
进程恢复与可靠多播
进程恢复涉及到的技术可以使一个或多个进程发生故障而不会严重影响到系统的其余部分。可靠多播与这个问题相关,它确保可以成功地把信息传输到一个进程集合。要保持进程同步,可靠多播通常是必需的。
分布式提交协议
原子性( atomicity)在很多应用程序中都是一个重要的特性。例如,在分布式事务中,就必须要保证一个事务中的所有操作全部发生或一个都不发生。在分布式系统中原子性的基础是分布式提交协议,我们将在本章中用单独节来讨论它。
故障恢复
最后,我们将介绍如何从故障中恢复。特别是,我们将考虑何时以及如何对一个分布式系统的状态进行保存以确保在以后恢复到该状态。
可靠的系统- 可用性
- 可靠性
- 安全性
- 可维护性
可用性( availability)被定义为系统的一个属性,它说明系统已准备好,马上就可以使用。通常,它指在任何给定的时刻,系统都可以正确地操作,可根据用户的行为来执行它的功能。换句话说,高度可用的系统在任何给定的时刻都能及时地工作。
可靠性(reliability)可靠性(reliability)是指系统可以无故障地持续运行。与可用性相反,可靠性是根据时间间隔而不是任何时刻来进行定义的。高度可靠的系统可以在一个相对较长的时间内持续工作而不被中断。这很微妙,但是与可用性相比,这是一个重要的不同。如果系统在每小时中崩溃1ms,那么它的可用性就超过99.9999%,但是它还是高度不可靠的。与之类似,如果一个系统从来不崩溃,但是要在每年8月中停机两个星期,那么它就是高度可靠的,但是它的可用性只有96%。这两种属性并不相同。
安全性(safety)安全性(safety)是指在系统偶然出故障的情况下能正确操作而不会造成任何灾难。例如,很多进程控制系统,比如那些用来控制核电站或把人送入太空的控制系统,就必须提供高度的安全性。这样的控制系统即使只是非常短时间瞬时故障,结果也将是灾难性的。过去的很多例子(以后还会有更多的例子)都说明了要建立安全的系统是多么困难。
可维护性( maintainability)最后,可维护性( maintainability)是指发生故障的系统被恢复的难易程度。高度可维护的系统可能具有高度的可用性,特别是在可以探测到故障并自动恢复时。但是,像我们在本章后面将看到的那样,从故障中自动恢复说起来简单,做起来就难了。
术语- Failure:失败,系统不能满足其承诺。
- Error:错误,它是系统状态的一部分,可能导致失败。
- Fault:故障,错误的原因
- Fault Tolerance:容错故障,继续正常运转,在发生故障时不失效
- Transient fault:发生一次就消失了。如果重复该操作,则故障消失
- Intermittent fault:发生,然后自动消失,然后再次出现,如此循环。
- permanent fault:故障部件被替换之前仍然存在的故障
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQ8w3pf8-1636346569420)(E:Study MaterialsTypora photosimage-20211027070118271.png)]
冗余如果系统是容错的,那么它能做的最好的事情就是对其他进程隐藏故障的发生。关键技术是使用冗余来掩盖故障。有三种可能:
- 信息冗余
- 时间冗余
- 物理冗余
在信息冗余中,添加额外的位可以使错乱的位恢复正常。例如可以在传输的数据中添加一段 Hamming 码来从传输线路上的噪声中恢复数据。
时间冗余在时间冗余中,执行一个动作,如果需要就再次执行。使用事务处理(在第1章中已经介绍)是这种方法的一个例子。如果一个事务处理中止,那么它就可以无害地重新执行。当错误是临时性或间歇性时,时间冗余特别有用。
物理冗余在物理冗余中,通过添加额外的装备或进程使系统作为一个整体来容忍部分组件的尖效或故障成为可能。物理冗余可以在硬件上也可以在软件上进行。例如,可以在系统中添加额外的进程;这样如果少数进程崩溃,系统还是可以正常工作。换句话说,通过冗余的进程可以获得高度容错性。
物理冗余是提供容错性的著名技术。它用在生物学(哺乳动物具有两只眼睛、两个耳朵,两个肺等)、飞行器(747具有四个引擎,而只使用三个)和体育(有多个裁判)中。物理冗余用在电子电路的容错中已经有多年了,了解如何在电子电路中使用它是有意义的。例如,考虑图8.2(a)中的电路。这里的信号依次通过设备A,B和C。如果它们中的一个发生故障,最后结果就可能是错误的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bdnmfyl1-1636346569422)(E:Study MaterialsTypora photosimage-20211027070822220.png)]
在图8.2(b)中,每个设备都被复制了三个。这样电路中的每一级都有三个表决电路,每个表决电路都是具有三个输入和一个输出的电路。如果输入中的两个或三个是相同的,那么输出就等于输人,如果所有的输入都是不同的,那么输出就是未定义的。这种设计被称为三倍模块冗余(Triple Modular Redundancy,TMR)。
假定元件A2发生故障,则每个表决电路V1、V2和V3获得两个好的(一致的)输入和一个无用的输入,它们中的每个都将正确值输出到第二级。这样A2故障的影响就完全被掩盖了,到B1、B2和B3的输入就与没有发生故障时完全相同。
现在考虑一下如果除了A2之外B3和C1也都发生了故障时的情形。即使发生这种情况,其影响也会被掩盖,三个最后的输出还是正确的。
为什么在每一级都需要三个表决电路呢?毕竟一个表决电路就可以发现并传递主要的观点。但是,一个表决电路只是一个组件,它可能发生故障。例如,假定V1发生故障,到B2的输人就是错误的,但是只要别的部分正常.工作,B2和 B3就会产生相同的输出,V4,V5和V6都会产生到第三级的正确结果。V1·发生故障的影响与Bl故障没什么区别,在两种情况下B1都产生错误的输出,但是两种情况下都在后面才进行表次。
尽管不是所有的容错分布式系统都使用TMR,但是这种技术还是很普遍的,它对容错系统是什么给出了一个清楚的解释。它与使用高度可靠的单个组件的系统不同,后者的组织不是容错的。当然,TMR也可以递归使用,例如在芯片内部使用TMR来使它高度可靠,而对于使用芯片的电路设计者来说,他们并不知道芯片的冗余性。
进程恢复 进程组 k-故障容忍进程组是建立容错系统方法的一部分,特别是在有一组相同的进程允许我们掩盖组中的一个或多个发生故障的进程的情况下。换句话说,我们可以复制进程并把它们组织在一个组中来用一个容错的组取代一个脆弱的进程。像前面讨论过的那样,有两种方法来进行复制:通过基于主进程的协议或通过复制写协议。
在容错的情况下,基于主进程的复制通常以主进程后备协议的形式出现。在这种情况下,以等级方式来组织一个进程组,其中一个主进程协调所有的写操作。在实践中,这个主进程是固定的,尽管如果需要可以用一个后备进程来接管它。实际上,如果主迸程崩溃,后备进程执行―些选举算法来选择一个新的主进程。
像我们在上一章中解释的那样,与基于团体的协议相同,复制写协议以主动复制的形式使用。这些解决方法把相同进程的集合组织到一个平等组中。这样做的主要优点在于这样的组没有单一的失败点,代价是分布式的协调。
使用进程组进行容错中一个重要的问题是需要多少复制。为了简化我们的讨论,我们只考虑复制—写系统的情况。如果系统能够经受k个组件的故障并且还能满足规范的要求,那么就被称为k容错(k fault tolerant)。如果这些组件(进程)是失败沉默的,那么具有k+1个组件就足够提供k容错。如果k个组件停止工.作,还可以用剩下的一个组件来得到响应。
另一方面,如果进程发生拜占庭失败,继续错误运行并发送出错误或随机的应答,那么最少需要2k+1个进程才能获得k容错。在最坏的情况下,k个失败的进程可以意外地(甚至是故意地)产生同样的应答,但是剩余的k+1个进程也会产生同样的回答,这样,客户或表决电路还可以相信多数进程的回答。
当然,说一个系统是k容错的,让k+1个相同的进程以票数胜过k个相同的应答在理论上是好的,但是在实践中很难想象这样的情况,即k个进程失败了,但是k+1个进程没有失败。这样,即使在容错系统中也需要某种统计分析。
与这种模式有关的一个不明显的前提是所有请求按相同的顺序到达所有的服务器,这个问题被称为原子多播问题(atomic nulticast problern)。实际上,这个条件可以稍微放松,因为读操作不会有问题而一些写操作也可以替换,但是还留有一般的问题。原子多播将在后面详细讨论。
把复制的进程组织在一个组中有助于提高容错性。正如我们提到的那样,如果客户可以根据它的表决机制做出决定,我们甚至可以容忍2k+1个进程中的k个进程得出错误的结果。但是,我们做出的假定是这些进程没有组合成团队来共同产生错误的结果。
通常,如果我们要求进程组达成一致,事情会变得更复杂。在很多情况下需要达到一致,例如,选择一个协作者,决定是否提交一个事务,在工作者之间划分任务以及同步。当通信和进程都很完美时,达成这样的一致通常是简单而又直接的,但是如果不是这样,就会出现问题。
分布式协议算法的-般目标是使所有的非故障进程就一些问题达成一致,而且在有限的步骤内就达成一致。这个问题有点复杂了,因为底层系统的不同假设需要不同的解决方案(假设解决方案存在)Turek和 Shasha(1992)区分了以下一些情况:
- 同步与非同步系统。在某个加锁步骤模式下,有且只有一个进程运行,该系统就称为同步的(synchronous)。正式地说,这表示,有一常量c≥1,如果有某个处理器执行了c+l步,其他进程最少执行1步。不是同步的系统就称为是异步的(asynchronous)。
- 通信延时受限与否。当且仅当每个消息使用全局和预定的最大时间传送时,延时是受限的。
- 消息传送是否已排序。
- 消息传输是通过单播或多播来完成的。
事实证明,只有在如图8.4所示的情况下才可能达成协定。在其他所有情况下,都不存在解决办法。注意,大多数实际的分布式系统都是假定进程是异步的,消息传输是单播的,通信延时是不受限的。因此,我们需要使用已排序(可靠)的消息传送,如 TCP/IP。图8.4显示了当进程发生故障时的分布式协定非凡本性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0caEIyIy-1636346569423)(E:Study MaterialsTypora photosimage-20211027083253835.png)]
故障检测 可靠的C-S通信 点对点通信 失败时的PRC语义 可靠的组间通信 可靠多播 可靠多播拓展- 无等级反馈控制
- 分等级反馈控制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJRSG7xo-1636346569424)(E:Study MaterialsTypora photosimage-20211027083902266.png)]
无等级反馈控制[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ckAtQqHJ-1636346569425)(E:Study MaterialsTypora photosimage-20211027084100520.png)]
分布式提交前面讨论的原子多播问题是一个称为分布式提交的更一般化问题中的一个例子。分布式提交的问题涉及到要使一个操作被进程组中的每个成员都执行或一个成员都不执行。在可靠多播的情况下﹐操作就是消息的传送。在分布式事务中,操作可能是单个站点上事务的提交,它是整个事务的一部分。分布式提交中的其他例子及其解决办法在(Tanisch 2000)中进行了讨论。
分布式提交通常以设立协作者的方式建立。在简单的方案中,协作者通知所有涉及到的称为参与者的其他进程是否(本地)按要求执行操作。这种方法称为单阶段提交协议(one-phase commit protocol)。如果有一个参与者不能真正执行该操作,那么就说明它存在着明显的缺陷,因为它没有办法来通知协作者。例如,在分布式事务的情况下,不可能进行本地提交,因为这会破坏并发控制约束。
基于XA协议的两阶段提交XA 是一个分布式事务协议,规定了事务管理器和资源管理器接口。
因此,XA 协议可以分为两部分:
- 事务管理器:作为协调者,负责各个本地资源的提交和回滚;
- 本地资源管理器:分布式事务的参与者,通常由数据库实现,比如 Oracle、DB2 等商业数据库都实现了 XA 接口。
基于 XA 协议的二阶段提交方法中,二阶段提交协议(The two-phase commit protocol,2PC),用于保证分布式系统中事务提交时的数据一致性,是 XA 在全局事务中用于协调多个资源的机制。
二阶段提交方法本质上是一种集中式的算法思想:为了保证它们的一致性,我们需要引入一个协调者来管理所有的节点,并确保这些节点正确提交操作结果,若提交失败则放弃事务。
两阶段提交协议的执行过程,分为投票(voting)和提交(commit)两个阶段,投票为第一阶段。以用户 A 要在网上下单购买 100 件 T 恤为例。
投票(CanCommit )阶段- 订单系统中将与用户 A 有关的订单数据库锁住,准备好增加一条关于用户 A 购买 100 件 T 恤的信息,并将同意消息“Yes”回复给协调者。
- 而库存系统由于 T 恤库存不足,出货失败,因此向协调者回复了一个终止消息“No”。
总结一下,该阶段是协调者问参与者 “你需不需要执行事务” ,参与者回复“Yes或No“的过程:
- 协调者(Coordinator,即事务管理器)会向事务的参与者(Cohort,即本地资源管理器)发起执行操作的 CanCommit 请求,并等待参与者的响应。
- 参与者接收到请求后,会执行请求中的事务操作,记录日志信息但不提交,待参与者执行成功,则向协调者发送“Yes”消息,表示同意操作;若不成功,则发送“No”消息,表示终止操作。
- 当所有的参与者都返回了操作结果(Yes 或 No 消息)后,系统进入了提交阶段。
一些注意事项:
- 参与者收到CanCommit 请求之后才会执行事务。响应Yes说明想要/可以提交;响应No表示不想/不能提交。
- 所有参与者都回复了才能进入提交阶段
- 由于库存系统操作不成功,因此,协调者就会向订单系统和库存系统发送“DoAbort”消息。
- 订单系统接收到“DoAbort”消息后,将系统内的数据退回到没有用户 A 购买 100 件 T 恤的版本,并释放锁住的数据库资源。
- 订单系统和库存系统完成操作后,向协调者发送“HaveCommitted”消息,表示完成了事务的撤销操作。
- 至此,用户 A 购买 100 件 T 恤这一事务已经结束,用户 A 购买失败。
总结一下,这个阶段就是协调者返回的”Yes或No“,向参与者发送 DoCommit 或 DoAbort 指令的过程:
- 若协调者收到的都是“Yes”消息,则向参与者发送“DoCommit”消息,参与者会完成剩余的操作并释放资源,然后向协调者返回“HaveCommitted”消息;
- 如果协调者收到的消息中包含“No”消息,则向所有参与者发送“DoAbort”消息,此时发送“Yes”的参与者则会根据之前执行操作时的回滚日志对操作进行回滚,然后所有参与者会向协调者发送“HaveCommitted”消息;
- 协调者接收到“HaveCommitted”消息,就意味着整个事务结束了。
一些注意事项:
- 必须收到所有的Yes才能发送DoCommit,这意味着所有系统都准备好执行了。一旦有一个No,表示分布式事务中参与的部分系统还没准备好处理事务,就必须所有系统都停下来,这样保证了事务的原子性。
- 同步阻塞问题:二阶段提交算法在执行过程中,所有参与节点都是事务阻塞型的。也就是说,当本地资源管理器占有临界资源时,其他资源管理器如果要访问同一临界资源,会处于阻塞状态。
- **单点故障问题:**基于 XA 的二阶段提交算法类似于集中式算法,一旦事务管理器发生故障,整个系统都处于停滞状态。尤其是在提交阶段,一旦事务管理器发生故障,资源管理器会由于等待管理器的消息,而一直锁定事务资源,导致整个系统被阻塞。
- **数据不一致问题:**在提交阶段,当协调者向参与者发送 DoCommit 请求之后,如果发生了局部网络异常,或者在发送提交请求的过程中协调者发生了故障,就会导致只有一部分参与者接收到了提交请求并执行提交操作,但其他未接到提交请求的那部分参与者则无法执行事务提交。于是整个分布式系统便出现了数据不一致的问题。
三阶段提交协议(Three-phase commit protocol,3PC),是对二阶段提交(2PC)的改进。
为了解决两阶段提交的同步阻塞和数据不一致问题,三阶段提交引入了超时机制和准备阶段:
- 在协调者和参与者中引入超时机制。如果协调者或参与者在规定的时间内没有接收到来自其他节点的响应,就会根据当前的状态选择提交或者终止整个事务。
- 在第一阶段和第二阶段中间引入了一个准备阶段,也就是在提交阶段之前,加入了一个预提交阶段。在预提交阶段排除一些不一致的情况,保证在最后提交之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC 把 2PC 的提交阶段一分为二,这样三阶段提交协议就有 CanCommit、PreCommit、DoCommit 三个阶段。
CanCommit阶段与二阶段提交一样
PreCommit阶段协调者根据参与者的回复情况,来决定是否可以进行 PreCommit 操作:
- 如果所有参与者回复的都是“Yes”,那么协调者就会执行事务的预执行:
- **发送预提交请求。**协调者向参与者发送 PreCommit 请求,进入预提交阶段。
- 事务预提交。参与者接收到 PreCommit 请求后执行事务操作,并将 Undo 和 Redo 信息记录到事务日志中。
- 响应反馈。如果参与者成功执行了事务操作,则返回 ACK 响应,同时开始等待最终指令。
- 假如任何一个参与者向协调者发送了“No”消息,或者等待超时之后,协调者都没有收到参与者的响应,就执行中断事务的操作:
- 发送中断请求。协调者向所有参与者发送“Abort”消息。
- 终断事务。参与者收到“Abort”消息之后,或超时后仍未收到协调者的消息,执行事务的终断操作。
DoCmmit 阶段进行真正的事务提交,根据 PreCommit 阶段协调者发送的消息,进入执行提交阶段或事务中断阶段:
-
执行提交阶段:
- 发送提交请求。协调者接收到所有参与者发送的 Ack 响应,从预提交状态进入到提交状态,并向所有参与者发送 DoCommit 消息。
- 事务提交。参与者接收到 DoCommit 消息之后,正式提交事务。完成事务提交之后,释放所有锁住的资源。
- 响应反馈。参与者提交完事务之后,向协调者发送 Ack 响应。
- 完成事务。协调者接收到所有参与者的 Ack 响应之后,完成事务。
-
事务中断阶段:
- 发送中断请求。协调者向所有参与者发送 Abort 请求。
- 事务回滚。参与者接收到 Abort 消息之后,利用其在 PreCommit 阶段记录的 Undo 信息执行事务的回滚操作,并释放所有锁住的资源。
- 反馈结果。参与者完成事务回滚之后,向协调者发送 Ack 消息。
- 终断事务。协调者接收到参与者反馈的 Ack 消息之后,执行事务的终断,并结束事务。
在 DoCommit 阶段,当参与者向协调者发送 Ack 消息后,如果长时间没有得到协调者的响应,在默认情况下,参与者会自动将超时的事务进行提交,不会像两阶段提交那样被阻塞住。
2PC 和 3PC 这两种方法,有两个共同的缺点,一是都需要锁定资源,降低系统性能;二是,没有解决数据不一致的问题。因此,便有了通过分布式消息来确保事务最终一致性的方案。
在 eBay 的分布式系统架构中,架构师解决一致性问题的核心思想就是:将需要分布式处理的事务通过消息或者日志的方式异步执行,消息或日志可以存到本地文件、数据库或消息队列中,再通过业务规则进行失败重试。这个案例,就是使用基于分布式消息的最终一致性方案解决了分布式事务的问题。
基于分布式消息的最终一致性方案的事务处理,引入了一个消息中间件(Message Queue,MQ),用于在多个应用之间进行消息传递。基于消息中间件协商多个节点分布式事务执行操作的示意图,如下所示。
仍然以网上购物为例。假设用户 A 在某电商平台下了一个订单,需要支付 50 元,发现自己的账户余额共 150 元,就使用余额支付,支付成功之后,订单状态修改为支付成功,然后通知仓库发货。
在该事件中,涉及到了订单系统、支付系统、仓库系统,这三个系统是相互独立的应用,通过远程服务进行调用。
根据基于分布式消息的最终一致性方案,用户 A 通过终端手机首先在订单系统上操作,然后整个购物的流程如下所示。
- 订单系统把订单消息发给消息中间件,消息状态标记为“待确认”。
- 消息中间件收到消息后,进行消息持久化操作,即在消息存储系统中新增一条状态为“待发送”的消息。
- 消息中间件返回消息持久化结果(成功 / 失败),订单系统根据返回结果判断如何进行业务操作。失败,放弃订单,结束(必要时向上层返回失败结果);成功,则创建订单。
- 订单操作完成后,把操作结果(成功 / 失败)发送给消息中间件。
- 消息中间件收到业务操作结果后,根据结果进行处理:失败,删除消息存储中的消息,结束;成功,则更新消息存储中的消息状态为“待发送(可发送)”,并执行消息投递。
- 如果消息状态为“可发送”,则 MQ 会将消息发送给支付系统,表示已经创建好订单,需要对订单进行支付。支付系统也按照上述方式进行订单支付操作。
- 订单系统支付完成后,会将支付消息返回给消息中间件,中间件将消息传送给订单系统。订单系统再调用库存系统,进行出货操作。
可以看出,分布式事务中,当且仅当所有的事务均成功时整个流程才成功。所以,分布式事务的一致性是实现分布式事务的关键问题,目前来看还没有一种很简单、完美的方案可以应对所有场景。
三种实现方法的对比 base理论base 理论包括基本可用(Basically Available)、柔性状态(Soft State)和最终一致性(Eventual Consistency)。
- 基本可用:分布式系统出现故障的时候,允许损失一部分功能的可用性。比如,某些电商 618 大促的时候,会对一些非核心链路的功能进行降级处理。
- 柔性状态:在柔性事务中,允许系统存在中间状态,且这个中间状态不会影响系统整体可用性。比如,数据库读写分离,写库同步到读库(主库同步到从库)会有一个延时,其实就是一种柔性状态。
- 最终一致性:事务在操作过程中可能会由于同步延迟等问题导致不一致,但最终状态下,数据都是一致的。
可见,base 理论为了支持大型分布式系统,通过牺牲强一致性,保证最终一致性,来获得高可用性,是对 ACID 原则的弱化。具体到今天的三种分布式事务实现方式,二阶段提交、三阶段提交方法,遵循的是 ACID 原则,而消息最终一致性方案遵循的就是 base 理论。
恢复 概述 稳定存储 检查点在容错的分布式系统中,回退错误恢复需要系统把它的状态有规律地保存到稳定存储中。分布式系统的状态已经在第5章进行了讨论。特别是,我们着重强调了记录一致全局状态的必要性,它也被称为分布式快照(distributed snapshot)。在分布式快照中,如果进程Р记录了一条消息的接收,那么就应该有一个进程Q记录了该消息的发送。毕竟消息必须是来自某个地方的。
在回退错误恢复方法中,每个进程都按时把它的状态保存到本地可用的稳定存储中。要在进程或系统失败之后进行恢复﹐就需要我们从这些局部状态中建立一致的全局状态。特别是,最好恢复到最近的分布式快照,这种快照也被称为恢复线路(recovery line)。换句话说,恢复线路就对应于最近的一致性切面,如图8.24所示。
在容错的分布式系统中,回退错误恢复需要系统把它的状态有规律地保存到稳定存储中。分布式系统的状态已经在第5章进行了讨论。特别是,我们着重强调了记录一致全局状态的必要性,它也被称为分布式快照(distributed snapshot)。在分布式快照中,如果进程Р记录了一条消息的接收,那么就应该有一个进程Q记录了该消息的发送。毕竟消息必须是来自某个地方的。
在回退错误恢复方法中,每个进程都按时把它的状态保存到本地可用的稳定存储中。要在进程或系统失败之后进行恢复﹐就需要我们从这些局部状态中建立一致的全局状态。特别是,最好恢复到最近的分布式快照,这种快照也被称为恢复线路(recovery line)。换句话说,恢复线路就对应于最近的一致性切面,如图8.24所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q2LzsKm3-1636346569426)(E:Study MaterialsTypora photosimage-20211027084757145.png)]



