可靠性
可靠性(Reliability)
系统的可靠性是指在规定的时间内及规定的环境下完成规定功能的能力,也就是系统的无故障运行概率。人们对可靠软件的典型期望包括:
- 应用程序表现出用户所期望的功能。
- 允许用户犯错,允许用户以出乎意料的方式使用软件。
- 在预期的负载和数据量下,性能满足要求。
- 系统能防止未经授权的访问和滥用。
可靠性不仅仅是针对核电站和空中交通管制软件而言,我们也期望更多平凡的应用能可靠地运行。商务应用中的错误会导致生产力损失(也许数据报告不完整还会有法律风险
故障与错误
造成错误的原因叫做故障(fault
在这类容错系统中,通过故意触发来提高故障率是有意义的,例如:在没有警告的情况下随机地杀死单个进程。许多高危漏洞实际上是由糟糕的错误处理导致的,像
安全性和活性
为了澄清这种情况,有必要区分两种不同的性质:安全性(safety)和活性(liveness
-
如果安全属性被违反,我们可以指向一个特定的时间点(例如,如果违反了唯一性属性,我们可以确定重复的防护令牌返回的特定操作
) 。违反安全属性后,违规行为不能撤销——损失已经发生。 -
活性属性反过来:在某个时间点(例如,一个节点可能发送了一个请求,但还没有收到响应
) ,它可能不成立,但总是希望在未来(即通过接受答复) 。
区分安全性和活性属性的一个优点是可以帮助我们处理困难的系统模型。对于分布式算法,在系统模型的所有可能情况下,要求始终保持安全属性是常见的。也就是说,即使所有节点崩溃,或者整个网络出现故障,算法仍然必须确保它不会返回错误的结果(即保证安全性得到满足
安全性和活性属性以及系统模型对于推理分布式算法的正确性非常有用。然而,在实践中实施算法时,现实的混乱事实再一次地让你咬牙切齿,很明显系统模型是对现实的简化抽象。例如,在故障恢复模型中的算法通常假设稳定存储器中的数据经历了崩溃。但是,如果磁盘上的数据被破坏,或者由于硬件错误或错误配置导致数据被清除,会发生什么情况?如果服务器存在固件错误并且在重新启动时无法识别其硬盘驱动器,即使驱动器已正确连接到服务器,也会发生什么情况?
法定人数算法依赖节点来记住它声称存储的数据。如果一个节点可能患有健忘症,忘记了以前存储的数据,这会打破法定条件,从而破坏算法的正确性。也许需要一个新的系统模型,在这个模型中,我们假设稳定的存储大多存在崩溃,但有时可能会丢失。但是那个模型就变得更难以推理了。算法的理论描述可以简单宣称一些事在假设上是不会发生的——在非拜占庭式系统中。但实际上我们还是需要对可能发生和不可能发生的故障做出假设,真实世界的实现,仍然会包括处理“假设上不可能”情况的代码,即使代码可能就是
这并不是说理论上抽象的系统模型是毫无价值的,恰恰相反。它们对于将实际系统的复杂性降低到一个我们可以推理的可处理的错误是非常有帮助的,以便我们能够理解这个问题,并试图系统地解决这个问题。我们可以证明算法是正确的,通过显示它们的属性总是保持在某个系统模型中。证明算法正确并不意味着它在真实系统上的实现必然总是正确的。但这迈出了很好的第一步,因为理论分析可以发现算法中的问题,这种问题可能会在现实系统中长期潜伏,直到你的假设(例如,时间)因为不寻常的情况被打破。理论分析与经验测试同样重要。
故障模型
系统故障是指硬件或者软件的错误状态,一般引进故障的原因是这些:部件的失效、环境的物理干扰、操作错误或不正确的设计。按照时间的长短,故障可以分为:永久性、间歇性、瞬时性。
故障的级别有:逻辑级故障、数据结构级故障、软件故障和差错故障、系统级故障。
硬件故障
硬件故障(hardware faults)譬如等等硬盘崩溃、内存出错、机房断电、有人拔错网线,任何大型的数据中心都可能出现这种错误。据报道称,硬盘的 平均无故障时间(MTTF mean time to failure)约为
为了减少系统的故障率,第一反应通常都是增加单个硬件的冗余度,例如:磁盘可以组建
我们通常认为硬件故障是随机的、相互独立的:一台机器的磁盘失效并不意味着另一台机器的磁盘也会失效。大量硬件组件不可能同时发生故障,除非它们存在比较弱的相关性(同样的原因导致关联性错误,例如服务器机架的温度
如果在硬件冗余的基础上进一步引入软件容错机制,那么系统在容忍整个(单台)机器故障的道路上就更进一步了。这样的系统也有运维上的便利,例如:如果需要重启机器(例如应用操作系统安全补丁
软件错误
另一类错误是内部的系统性错误(systematic error
- 接受特定的错误输入,便导致所有应用服务器实例崩溃的
BUG 。例如2012 年6 月30 日的闰秒,由于Linux 内核中的一个错误,许多应用同时挂掉了。 - 失控进程会占用一些共享资源,包括
CPU 时间、内存、磁盘空间或网络带宽。 - 系统依赖的服务变慢,没有响应,或者开始返回错误的响应。
- 级联故障,一个组件中的小故障触发另一个组件中的故障,进而触发更多的故障。
虽然软件中的系统性故障无法避免,但我们还是有很多小办法,例如:仔细考虑系统中的假设和交互;彻底的测试;进程隔离;允许进程崩溃并重启;测量、监控并分析生产环境中的系统行为。如果系统能够提供一些保证(例如在一个消息队列中,进入与发出的消息数量相等
人为错误
设计并构建了软件系统的工程师是人类,维持系统运行的运维也是人类,人非圣贤,孰能无过。一项关于大型互联网服务的研究发现,运维配置错误是导致服务中断的首要原因,而硬件故障(服务器或网络)仅导致了
- 以最小化犯错机会的方式设计系统。例如,精心设计的抽象、
API 和管理后台使做对事情更容易,搞砸事情更困难。但如果接口限制太多,人们就会忽略它们的好处而想办法绕开。很难正确把握这种微妙的平衡。 - 将人们最容易犯错的地方与可能导致失效的地方解耦(decouple
) 。特别是提供一个功能齐全的非生产环境沙箱(sandbox) ,使人们可以在不影响真实用户的情况下,使用真实数据安全地探索和实验。 - 在各个层次进行彻底的测试,从单元测试、全系统集成测试到手动测试。自动化测试易于理解,已经被广泛使用,特别适合用来覆盖正常情况中少见的边缘场景(corner case
) 。 - 允许从人为错误中简单快速地恢复,以最大限度地减少失效情况带来的影响例如,快速回滚配置变更,分批发布新代码(以便任何意外错误只影响一小部分用户
) ,并提供数据重算工具(以备旧的计算出错) 。 - 配置详细和明确的监控,比如性能指标和错误率在其他工程学科中这指的是遥测(telemetry
) (一旦火箭离开了地面,遥测技术对于跟踪发生的事情和理解失败是至关重要的。 )监控可以向我们发出预警信号,并允许我们检查是否有任何地方违反了假设和约束。当出现问题时,指标数据对于问题诊断是非常宝贵的。 - 良好的管理实践与充分的培训。
可靠性模型
与故障模型想对应的,就是系统的可靠性模型。常用的有以下三种:时间模型、故障植入模型和数据模型。
可靠性指标
可靠性指标,主要有以下几个:
平均无故障时间(MTTF-Mean Time To Failure)
它表示一个系统平均情况下,正常运行的时间。
与它相关的指标是“失效率”U,关系:U = 1 / MTTF。
平均故障修复时间(MTTR-Mean Time To Fix/Repire)
平均每次修复所需要的时间
平均故障间隔时间(MTBF-Mean Time Between Failure)
一看就知道,MTBF = MTTF + MTTR。
在实际情况下,一般
可靠性计算
一个系统的可靠性计算往往不能直接得出。这是因为计算机系统是一个复杂的系统,影响其可靠性的因素也非常复杂。所以我们需要为其建立适当的数据模型,把大系统划分为若干子系统,然后再根据一定原则进行组合计算。
这种计算方法,可以简化分析的过程。
对于系统的划分,我们可以把它分为:串联系统、并联系统、模冗余系统、混联系统
计算这些系统可靠性时,我们需要计算出每个子系统的失效率,然后根据概率的加法原则(串联系统)和乘法原则(并联系统)进行综合运算,最后得出整个系统的可靠性。