第8章 分布式系统之容错技术
将分布式系统与单机系统区分开的一个特征就是部分故障的概念:系统的部分失败了而剩余部分继续看似正确地运行。
在分布式系统设计里的一个重要目标就是构建一个系统,使其能自动地从部分故障中恢复而不会严重影响整体性能。尤其是,无论故障何时发生,系统应该能在故障修复的同时,继续以可接受的方式运行。换句话说,人们期望分布式系统是容错的。
在这一章里,我们将仔细地研究容错技术。在介绍一些背景知识后,我们将通过进程组来研究进程的容错能力。在这种情形中,多个相同进程协作提供单个逻辑进程的视角,来保证一个或者多个进程发生故障而不被客户端感知到。在进程组中一个极其困难的点是在多个组成员间就该执行客户端请求的哪个操作达成一致。截止现在,Paxos是一个被广泛采用但非常复杂的算法,我们通过从底层向上的方式构建Paxos算法来解释它。类似地,我们会仔细地检查达成一致性的情形。
容错和可靠通信是紧密相关的。在介绍完可靠的客户端-服务器通信后,我们重点关注可靠的集群通信,尤其是原子广播。在原子广播中,一条消息要么投递给所有没有故障的进程,要么一个也没投递。有了原子广播之后,会使得开发容错解决方案变得更简单点。
原子性是一个对许多应用都很重要的性质。在这一章中,我们重点关注已知的分布式提交协议,使用分布式协议,可引导多个进程要么一起提交各自的本地任务,要么一起丢弃并返回之前的系统状态。
最后,我们将研究如何从故障中恢复。尤其是,我们会考虑应该何时且怎样保存分布式系统的状态,以便支持后面能恢复到该状态。
第8.1节 容错技术背景介绍
容错在计算机科学里已进行了许多研究。在这一节里,我们从介绍跟故障处理相关的基本概念开始,接着讨论故障模型,也会讨论冗余这一个故障处理的核心技术。
第8.1.1小节 基本概念
为了理解在分布式系统中容错的作用,我们首先要仔细研究研究分布式系统中容错的实际含义。容错跟可靠系统紧密相关。可靠性是一个术语,涵盖了许多有用的要求,比如
- 可用性(时间点)
- 可靠性(时间段)
- 安全性
- 可维护性
我们定义可用性为一个系统能否立即可用的性质。一般来说,可用性指的是系统在任意时刻正常运行且代表用户执行操作的可能性。换句话说,一个高可用的系统是一个在任意给定时刻有最高可能在运行的系统。
可靠性指的是一个系统无故障持续运行的性质。跟可用性相比,我们定义可靠性为一个时间段,而不是一个时间点。一个高度可靠的系统是一个在相对长的时间内有最高可能无故障运行的系统。当跟可用性相比时,这是一个微小但重要的区别。比如,一个系统平均每隔1小时随机1个毫秒宕机,则这个系统的可用性为,但却不可靠。类似地,一个系统永远不宕机,但每年8月有两个礼拜关闭,则这个系统是高可靠的,但可用性仅为
。注意,可用性和可靠性是有区别的。
安全性指的是当没有灾难发生时,一个系统何时会暂时地出现故障而不能正常运行。比如,诸如核电站或者载人航天等多过程控制系统,需要提供高度的安全性。如果这些控制系统临时一小会出现故障,则后果都是灾难性的。过去的许多系统都表明构建安全的系统是多么的难。
最后,可维护性指的是一个有故障的系统能被修复的容易程度。一个具有高度可维护性的系统可能会展示出高度的可用性,尤其是当故障能被自动检测和自动修复时。但是,从故障中自动恢复是说起来容易做起来难。
通常要求可靠系统也提供高安全性,尤其当涉及诸如完整性等问题时。
当一个系统不满足需求时,就可以说一个系统出故障了。特别地,如果设计一个分布式系统是为了给用户提供若干个服务,当该系统不能提供这些服务中的至少一个时,则就说该系统出故障了。
错误是系统状态的一部分,出错会导致出故障。比如,当跨网络来传输数据包时,预期会有一些包到达接收端时被损害。在这种情况下,损害意味着接收端可能错误地解释一个位,或者不能检测到一些包已到达。
错误的原因叫故障。显然,找出导致错误的原因很重要。比如,一个有错误或者不良的传输介质可能很容易就将包损害了。在这种情况下,移除故障相对简单点。但是,在无线网路中,传输错误也可能是由恶劣天气条件导致的。改变天气来减少或者预防错误是有一定挑战性的。
一个崩溃的程序显然也是一个故障,可能是由程序遇到有bug的代码导致的。bug的原因通常都是程序员。
构建可靠系统跟故障控制紧密相关。如Avizienis等人解释的那样,可区分预防故障、容忍故障、移除故障、预测故障等。这里,我们最关心故障容忍,意味着即使出现故障,系统仍能提供服务。比如,从某个意义上讲,在传输包时应用错误校正码是有可能容忍相对较低的传输线,降低一个可能会导致故障的错误的发生概率。
通常,把故障分为暂时性故障、间歇性故障、永久性故障等。
- 暂时性故障只会发生一次,然后就消失。如果重复该操作,则故障就消失。比如,一只鸟飞过微波发射器可能会导致网络中丢掉某些位。如果传输超时且重传包了,则下次就正常工作了。
- 间歇性故障发生了,一会自行消失,一会又出现了。比如,一个连接器上的松散接触点通常会导致间歇性故障。间歇性故障通常会导致严重后果,因为很难诊断间歇性故障。通常,当故障医生出现时,系统就工作正常了。
- 永久性故障是故障发生了就会一直存在直到故障组件被移除。比如烧坏的芯片、软件bug、磁盘头坏了等。
第8.1.2小节 故障模型
发生故障的系统是无法充分提供其设计的服务。如果把分布式系统看做是彼此之间及与客户端之间通信的服务器的集合,则不能充分地提供服务意味着:服务器或者通信通道没有按照预期的方式运行。但是,一个有故障的服务器自身可能并不是我们要寻找的故障。如果这类服务器依赖其他服务器来提供服务,则可能需要去其他地方查找出错的原因。
这种依赖关系大量出现在分布式系统中。一个出故障的硬盘可能会使得一个提供高可靠性文件系统的文件服务器变得困难重重。如果这样的一个文件服务器又是一个分布式数据库的一部分,则整个数据库的正常运行可能有风险,因为仅有部分数据可被访问到。
为了更好地理解一个故障有多严重,已开发出多种故障分类方法,其中一种是由Cristian和Hadzilacos描述的分类方法:
- 崩溃故障
虽然停机了,但是在停机前一直正常工作; - 遗漏故障:无法对传入请求作出响应
接收遗漏:无法接收传入的消息
发送遗漏:无法发送消息 - 超时故障
超出指定时间间隔作出响应 - 响应故障:响应不正确
值故障:响应值是错误的
状态转换故障:偏离正确的控制流 - 任意故障
可能在任意时间作出任意响应
什么是计时故障?
当响应超出指定的实时间隔时,就会发生计时故障。
计时故障举例
- 对流视频来说,如果没有足够的缓冲区来容纳传入的数据,则过快提供数据可能会轻易地给接收者带来麻烦。
- 服务器响应太慢。
什么是响应故障?
当服务器的响应不正确时,就发生了响应故障。
响应故障有两类情形:
- 值故障
表现:给定一个请求,服务器给出错误的响应。
示例:如果一个搜索引擎返回的网页跟任何一个搜索关键词都不相关,则该搜索引擎出现了值故障。 - 状态转换故障
表现:当服务器对传入的请求作出意料之外的反应时,则发生了状态转换故障。
示例:如果服务器接收到一个其无法识别的消息,且没有采取任何措施来处理,则该服务器发生了状态转换故障。
什么是拜占庭故障?
- 最严重的的故障;
- 当发生拜占庭故障时,客户端需要做好最坏的打算;
问题:当进程P不能感知到进程Q的任何操作时,进程P可以得出“进程Q已经停机了”的结论吗?
区分两类分布式系统:
- 异步分布式系统
因为在一个异步系统里,不对进程的执行速度和消息的传递时间做任何假设。所以当进程P不再感知到来自进程Q的任何操作时,进程P不能得出“进程Q已经崩溃”的结论。有可能进程Q只是运行太慢,或者进程Q发送给进程P的消息丢失了。 - 同步分布式系统
在一个同步系统里,进程执行速度和消息传递时间都是有界的。这意味着当期望进程Q做一些事但进程Q不再有活动时,进程P可得出“进程Q已经停机了”的结论。
假设一个分布式系统是部分同步的:在大多数情况下,该系统表现为同步系统,但该系统以异步方式运行的时间却没有边界。
假设进程P尝试检测进程P是否发生了故障,将停机故障按照严重程度来分类:
- 停止失败故障
- 噪声失败故障
- 静默失败故障
- 安全失败故障
- 任意失败故障
什么是停止失败故障?
- 能被可靠地检测到的崩溃故障;
- 假设不存在有故障的通信链路;
- 假设故障检测进程P对来自进程Q的响应设置了最坏情形延迟;
什么是噪声失败故障?
- 不能得出进程Q已经崩溃的结论;
- 存在某段时间进程P对进程Q的检测是不可靠的;
什么是静默失败故障?
假设通信链路没有故障,但进程P不能区分崩溃故障和遗漏故障;
什么是安全失败故障?
进程Q可发生任意良性故障,这些良性故障没有任何坏处。
什么是任意失败故障?
进程Q可能以任何可能的方式失败,除了对其他进程有害外,该故障是不可观察的。
必须要对任意类型失败故障做处理。
解释:
- 异步行为是一个例外,表示可以使用超时来得出“进程已经崩溃”的结论。
- 在实践中,必须设计故障容错解决方案来承受不正确地检测到进程已经停机的情况。
第8.1.3节 通过备份来进行故障屏蔽
如果一个系统要具备容错能力,则最好的办法就是向其他进程屏蔽故障的发生。故障屏蔽使用的核心技术就是使用冗余。
有3类冗余:
- 信息冗余;
- 时间冗余;
- 故障冗余;
什么是信息冗余?
使用信息冗余,就是添加额外的位以允许从乱码中恢复。
示例:将Hamming码添加到要传输的数据中,以便从有传输线的噪声的情况中恢复数据。
什么是时间冗余?
使用时间冗余,就是执行一个操作后,可以按需再执行一次。
示例1:在事务中就使用了时间冗余。如果一个事务被中止了,则重做该事务不会有坏处。
示例2:当预期没有响应时,就重新发送请求到服务器。
适用于处理瞬时故障或者间歇性故障。
什么是物理冗余?
使用物理冗余,需要添加额外的设备或者进程到系统中,使得系统有可能作为一个整体来容忍部分组件丢失或者故障。
物理冗余可以硬件实现,也可以软件实现。
软件冗余示例:可以添加额外的进程到系统中,以便如果有少数进程崩溃,系统仍可以正常运行。
通过进程冗余可以提供高度的容错能力。
注记8.1 精确定义可用性和可靠性
如何精确地定义可用性和可靠性?
- 可用性:
- 可靠性:
定义 可用性 长期可用
在时间段
内一个组件的可用性
:该组件在这段时间内连续正常运行的平均时间占比。
表示一个长期可用的组件。
传统意义上,容错跟三个指标有关:
- 平均出故障时间
MTTF
:直至出现一个故障的平均时间 - 平均恢复时间
MTTR
:修复一个故障需要的平均时间 - 平均两次故障间隔时间
MTBF
就是MTTF+MTTR
所以定义可用性:
注意
- 只有精确定义了一个故障是什么之后,上述的指标才有意义。
- 确认故障的发生并不是那么的显然。
定义 可靠性
在时间段
内一个组件的可靠性
:假设时间
时组件是正常的,则该组件在这个时间段内连续正常运行的条件概率。
推导满足的关系式
假设一个有个同样组件的系统,
表示在时刻
正常运行的组件的个数,
表示在时刻
出故障的组件的个数。则:
用导数表示组件出故障的速率,用导数
除以
可得故障率函数
:
又因为,所以:
假设组件不会老化,则故障率是一个常数,即,则
因为,可得:
结论
如果忽略一个组件的老化,则一个常数故障率会导致一个满足指数分布的可靠性函数。
第8.2节 进程的弹性
问题:在分布式系统中如何实现故障容错?
本节主要内容:
- 首先,讨论如何防止进程故障;
- 然后,讨论进程集群的一般设计问题,以及一个容错的进程集群。
- 最后,讨论当至少一个成员不被信任来提供正确答案时,如何在进程集群内达成一致。
网友评论