1.2 可靠性

每个人对某些事物是否可靠都有直观的想法。对于软件,典型的期望包括:

  • 应用执行用户期望的功能
  • 可以容忍用户犯错或以意料之外的方法使用软件
  • 对于必需的用例,在期望的负载和数据量下,它的性能足够好
  • 系统可以阻止任何非授权的访问和滥用

如果这些合在一起称之为“正常工作”,那么我们就可以简单的理解为“可靠性”是指“能够持续正常工作,即使发生故障”。

发生问题就是指故障,系统对故障的预料和处理被称之为容错性或者弹性。前者会有些许误导:它建议我们能构造一种能容忍所有可能的故障的系统,这当然是不现实的。如果整个地球被黑洞吞噬了,这种故障的容忍需要太空中的虚拟主机,如果有幸获得批准。所以谈论对某些类型故障的容忍才有意义。

需要注意的是故障跟失效不一样。故障通常定义为系统的一个组件偏离其规范,而失效是整个系统都停止提供服务。将错误发生率降至0是可能的,因此通常情况下最好设计故障容忍机制以防止故障导致失效。本书会包含几项用不可靠部件构建可靠系统的技术。

与直觉恰恰相反,在这样容错的系统中,故意诱发故障提高故障率是合理的,例如在不警告的情况下随机杀死单个进程。许多致命的BUG实际上是由不好的故障处理引起的。通过故意诱发故障,你可以保证容错机制可以持续受到检验和测试,这样可以提高你的自信,当故障自然产生时可以被正确地处理。NetflixChaosMonkey就是这种方式的一个例子。

比起预防故障,虽然我们更倾向于容错,但是很多时候预防比纠错更好。安全问题就是一个,例如:一个黑客破解了系统并获取到访问敏感数据的权限,这种事情是不可逆的。然而,本书主要是处理那种可以纠正的故障,如下所述。

1.2.1 硬件故障

当我们想起系统故障的原因,第一个想到的就是硬件故障。磁盘损毁、内存出错、电网停电、有人错拔了网线。任何一个在大数据中心工作过的人都可以告诉你,当你有大量机器的时候,这些错误会一致发生。

人们声称硬盘的平均到达失效时间(MTTF)是1050年,因此,一个有10000块硬盘的存储集群,我们可以认为平均每天都会有一个硬盘坏掉。

为了减少系统的失效几率,我们最初的应对措施通常是为单个硬件组件增加冗余。硬盘会被设置在磁盘阵列(RAID)上,服务器可能有双重电力供应或者支持热插拔的CPU,数据中心会有电池和发电机作为备用电源。当一个组件失效,冗余组件可以替代。这种方法不能完全预防硬件问题导致的系统失效,但是易于理解而且可以保证机器运行数年不中断。

直到最近,冗余硬件组件对大多数应用已经足够,因为它可以让单个机器几乎不失效。只要你可以将备份很快地存储到一台新机器上,对大多数应用而言,即使发生失效,停机时间也不会是灾难性的。因此,只有那种高可用性的小型应用会使用多机冗余。

然而,随着数据量和应用计算量的增加,很多应用会使用更多的机器,硬件故障也会成比例的增加。而且,一些云平台,例如Amazon Web Services,不警告就失效的虚拟机实例是相当常见的,因为平台被设计为灵活性和弹性比单机可靠性更重要。

今后的趋势会是这样,通过优先使用软件容错技术或增加冗余硬件,系统可以容忍整台机器的丢失。这种系统还有操作上的优势:如果要重启机器,一个单服务器系统需要计划停机时间(例如操作系统打安全补丁),但是可容忍机器失效的系统可以一次打一个节点的补丁,而不需要让整个系统停机。

1.2.2 软件故障

我们通常认为硬件故障是随机和独立的:一台机器的硬盘损坏不意味着另外一个硬盘即将损坏。它们之间没有很强的相关性,否则不太可能大量的硬件会同时失效。

另一类故障是系统内的系统错误。这种故障更难预料,因为它们之间有相互联系,比起不相关的硬件故障,它们会引起更多的系统失效。例如:

  • 一个当有特殊输入时导致应用服务器的每个实例都崩溃的BUG。例如:由于2012630号的闰秒,一个BUG导致Linux内核上的许多应用同时挂起。
  • 一个失控的进程导致某些共享资源----CPU时间、内存、硬盘空间或网络带宽被耗尽。
  • 一个系统依赖的服务变慢,反应迟钝,或开始返回中断回应。
  • 级联失效,一个组件中的小故障引起另一个组件的故障,并依次引起更多的故障。

在被不寻常的情况触发前,引起这种软件故障的BUG经常会潜伏很久。那种情况暴露出软件对自己的环境做了多种假设,这些假设通常是正确的,但出于某些原因最终不正确了。

软件中的系统错误没有快速的解决方案。许多小事情会有帮助:在构造过程中谨慎考虑系统中的假设和交互作用;彻底测试;进程隔离;允许进程崩溃和重启;计量、监控和分析系统行为。如果一个系统被期望提供一些保证(例如,在消息队列中,输入的消息数量与输出相等),运行时可以不断地自检,并且当有差异时提出警报。

1.2.3 人为故障

人类设计和构建了软件系统,保持系统运行的操作者也是人类。即使他们有最好的意图,但人类依然是不可靠的。例如,一项针对大型互联网服务的研究发现操作者的配置错误是导致中断的首要因素,而硬件故障只占10%25%

怎样才能在人类不可靠的情况下让我们的系统可靠呢?最好的系统结合了若干方法:

  • 设计系统时尽量减少错误发生率。例如,涉及良好的抽象化、API和管理员接口让“做正确的事情”更容易,并阻止“错误的事情”。然而,如果接口有过多的限制,会减少工作人员的收益,所以这是个难以捉摸的平衡。
  • 分离人们犯错最多的地方与可以导致失效的地方。尤其是提供全功能的非生产沙盒环境,供人们在不影响实际用户的情况下使用真实数据来安全地探索和实验。
  • 在各个级别上充分地测试,从单元测试到全系统集成测试和手工测试。自动化测试已经被广泛使用,能覆盖日常操作很少达到的角落的测试案例尤其有用。
  • 允许从认为错误快速简单地复原,将失效的影响最小化。例如,让配置回滚更快速,逐步推广新代码(这样任何意外BUG之影响少量用户),提供重新计算的工具(防止旧的计算是错误的情况)。
  • 设置详细的、清晰地监控,例如性能矩阵和错误率。在其他工程学科,这被称为遥测技术。(一旦火箭离开地面,遥测技术对追踪状态是必不可少的)监控机制可以展示提前警告信号,允许我们检查哪些假设和约束正在被违反。当问题发生时,矩阵对诊断很有帮助。
  • 实施好的管理实践和培训----一个复杂和重要的方面,但是超出本书范围。

1.2.4 可靠性有多重要?

可靠性不只是核电站和航空交通控制软件所需要得,更多的一般性应用同样期望可靠地工作。商业应用中的BUG会导致生产力损失(以及法律风险,如果报表不正确),电子商务网站的运行中断会造成巨大收入损失成本,并且会损坏声誉。

即使在“非关键”的应用中,我们队用户同样负有责任。设想一个在照片应用中存储了孩子们所有的照片和影响的父母。如果数据库突然崩溃,他们会是什么感受?他们知道如何从备份中还原吗?

还有些情况,我们可能为了减少开发成本或运营成本来牺牲可靠性,但是在这种投机取巧中我们应该都没有意识到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值