来自复杂系统故障的十八条经验

  • 郑柯

2012 年 9 月 14 日

话题:云计算DevOps架构文化 & 方法

连城是一名曾工作于网易杭州研究院和百度的自由开发者,也是《Erlang/OTP 并发编程实战》及《Erlang 并发编程(第一部分)》的译者,前不久,他在自己的博客上翻译了一篇文章《复杂系统故障面面观》,作者是来自芝加哥大学认知技术实验室的医学博士 Richard I. Cook,文中总结了十八条关于复杂系统故障的经验,讨论了故障的性质、如何评估故障、如何推断故障肇因等方面。

  • 复杂系统本质上都是高风险系统。

    各种备受瞩目的复杂系统都是高风险系统,这是它们固有的内在属性。尽管风险事故的爆发频度时有高低,导致系统固有高风险性的内因却无从化解。这些风险又催生了各式各样的风险防范措施,进而塑造了形形色色的复杂系统。

  • 复杂系统都对故障严加防范并且行之有效。

    故障造成的高昂代价促使人们逐渐构筑起重重防范措施来抵御故障。其中既包括必要的技术措施,也包括多种机构性措施、制度性措施和监管性措施。

  • 灾难性事故是由多起故障共同造成的——单点故障不足以兴风作浪。

    重大灾难性事故往往是由多起无足轻重的轻微故障共同导致的系统性的意外事故。这些轻微故障中的每一起都是事故的诱因,但只有当它们叠加在一起时,才会酿成事故。换言之,故障的发生概率比重大系统事故的发生概率要高得多。

  • 复杂系统中潜伏着变化多端的故障组合。

    除非真的发生事故,否则我们也很难看出这些故障如何会诱发事故。不断演变的技术和工作机构,再加上人们为了排除故障而付出的种种努力,使得故障也不断地发生变化。

  • 复杂系统运转时总是处于降级模式。

    由上一条可知,运转中的复杂系统总是残缺不全。之所以还能运转,是因为系统内备有充足的冗余部件,即便存在诸多缺陷,人们仍然有办法让它工作。从以往的事故评估结果来看,事发之前系统几乎都出现过险些酿成灾难的“准事故(proto-accident)”。系统的运作过程是动态的,各种(机构、人员、技术)部件会不断发生故障进而被更替。

  • 灾难总是近在咫尺。

    在从业人员的身边,各种潜在故障每时每刻如影随行。所有复杂系统都有可能导致灾难性的后果,这是它们的标志性特征之一。人们不可能完全杜绝这类灾难性故障;这是由系统自身的性质决定的。

  • 在事发之后将事故归咎于某一“罪魁祸首”的做法是完全不可取的。

    重大故障都是由多重失误共同造成的,因此,事故背后根本就不存在孤立的“罪魁祸首”。这种将事故归咎于某一“罪魁祸首”的做法无法反映故障的技术本质;之所以抓住某一局部力量或事件不放并加以责难,无非为了迎合社会和文化诉求罢了。

  • 事后成见会扭曲事故评定人员的认知。

    在已知事故后果的情况下,人们会产生一种错觉,倾向于认为当事人理应更早注意到酿成事故的种种事件。这意味着人们无法客观地分析事故经过。已然了解事故后果的事故分析人员往往会先入为主,难以站在当事人的角度忠实地还原事故经过。当事人似乎“理应注意到”这些因素“必将”导致事故。事后成见一直是事故调查中的主要障碍,尤其是在有专家参与的时候

  • 操作人员分饰二角:他们既是故障的始作俑者,也是故障的防范者。

    系统内的从业人员一边操纵系统从事生产,一边防范事故的发生。外界很少有人能够认识到这一角色的二重性。系统正常运转时,唱主角的是生产角色;事故发生后,主角则换成了故障防范角色。实际上,系统操作人员一直长期且持续地分饰二角,这一点往往为外界所误解。

  • 当事人的举动完全是在冒险。

    事故发生之后,人们往往会认为早在事发之前导致事故的重大故障就已经在所难免,之所以最终会酿成事故,是因为当事人在故障迫近时处理失当或玩忽职守。但实际上,当事人在采取行动时完全是在冒险,他们无法预知自己的行动会导致什么后果。灾后分析通常都不会将这些行为判作明智之举。反过来看:即便处理得当,也不过是瞎猫碰上死老鼠,无法得到广泛认同。

  • 风口浪尖上的行为令一切模糊性消失殆尽。

    各种组织机构都存在一定的模糊性,而且这种模糊性往往是蓄意造成的,它体现在生产目标、资源使用效率、运作成本,以及对不同程度的潜在事故的容忍度等多个方面。然而在评判那些被抛至风口浪尖的从业人员的行为时,这些模糊性却消失殆尽。发生事故之后,当事人的行为往往会被视为“失误”或“违规”,但这类评判带有严重的事后成见,往往无视业绩压力等其他诱因。

  • 从业人员会对复杂系统进行调整。

    从业人员及一线管理者会积极调整系统,一边扩大产值一边减少事故。这种调整每时每刻都在进行,包括:(1)系统重组,避免脆弱部件遭受故障。(2)集中稀缺资源,应对关键需求。(3)留出后路,用以躲避或修复各种可预期及不可预期的故障。(4)针对系统性能的变化建立各种早期检测手段以妥善紧缩生产规模,或通过其他手段提高系统的恢复能力。

  • 复杂系统中的专业人才不断更替。

    复杂系统中时刻存在着身怀不同程度的专业知识的从业人员和受训人员。有关专业知识的关键问题主要表现在(1)对能够胜任最困难、最艰巨的生产任务的稀缺专业人才资源的需求,以及(2)为了应对未来需求而进行的技术储备。

  • 变化会引入新的故障。

    在可靠性较高的系统中,重大事故的发生频率较低,这使得人们更乐于接受变化,尤其是以减少影响较小的频发性故障为目的引入新技术。然而这些变化有可能会引入新的、后果严重的偶发性故障。在应用新技术清除已知的系统故障或追求更高的性能的同时,往往会埋下可能引发新的大规模灾难性故障的隐患。不少情况下,比起采用新技术清除掉的那些故障,这些新的、罕见的灾难性事故所造成的影响甚至更加恶劣。

  • 抵御未来事件的效果受限于人们看待“肇因”的方式

    发生事故之后,为了防范事故中的“人为失误”,人们通常会想方设法阻断各种可能“导致”事故的事件。这种做法治标不治本,在事故防范方面起到的作用十分有限。实际上,由于潜在故障的模式不断地发生变化,相同事故重复发生的概率非常低。这类事后防范措施往往难以起到增强安全性的作用,反而还会加重系统的耦合性和复杂性。这么做不仅会催生更多潜在故障,而且还会加剧事故的排查难度。

  • 安全性是系统整体的特性,而不是系统中各部件的特性。

    安全性是系统的自发属性;它不是独立的个人、设备、组织中的某个部门或系统所能决定的。无论何时,安全性在任何系统中都是动态的;系统自身持续不断的变化必然导致灾难性故障及其应对方式发生相应的变化。

  • 人们持续不断地营造安全的环境

    无故障运营的背后凝结着人们付出的种种努力,他们想方设法将系统的性能波动控制在可承受范围内。然而系统的运转过程从来都不是一帆风顺的,迫于周遭条件的变化,从业人员必须及时采取措施,不断营造安全的环境。这些措施通常都出自一组经过充分演练的对策集;但有时也会出现新颖的策略组合或完全创新的解决方案。

  • 无故障运营需要故障处理相关的经验。

    只有真刀真枪地处理过故障的人才能识别出灾难性故障,并成功地将系统的性能波动维系在可承受范围之内。对于具有内在高风险性的系统,运维人员应当以把控系统整体运作情况为主,正确认识到事故的必然性并予以重视。安全性的提升离不开对意外事故有正确认识的运维人员;同时,运维人员也必须清楚地认识到自己采取的措施会如何影响系统,如何令系统逼近或远离极限情况。

  • 云计算DevOps架构文化 & 方法