您好,欢迎收听Kodish,一个探索现代开发者生活的节目。加入我们,一起深入探讨编程语言和框架、数据和事件驱动架构以及个人和团队效率等主题,所有内容都专为开发者和工程领导者量身定制。本期节目是我们“工具与技巧”系列的一部分。
欢迎收听本期Kodish节目。我是Marcus Blankenship,Salesforce的高级工程经理。今天我的嘉宾是Robert Blumen,Salesforce的首席DevOps工程师。欢迎,Robert。谢谢,Marcus。
我真的很期待这一期节目,因为它与我的内心息息相关。我们将讨论根源分析的替代方案,尤其是在出现问题和事情出错时。我们将讨论常见的根源分析方法,以及为什么它们不是思考复杂系统故障的最佳方法。最后,我们将分享一些关于如何更好地思考如何改进复杂系统的想法。所以
Robert,什么是根源分析?好的,根源分析是指人们事后分析故障以识别原因的不同方法。在许多不同的领域,这不仅仅是我们IT领域面临的问题。当我研究这方面的文献时,我发现许多不同领域的专业人士,例如医学、工业事故、航运、
航空领域,都会遇到所谓的事件或故障,即发生了不好的事情,一些你不想看到的事情。在IT领域,这意味着人们无法查看电子邮件,或者无法从企业获得服务。在其他医学领域,也许病人死了,船沉了,飞机坠毁了。你谈论的是非常严重的停机或故障,甚至可能导致人员伤亡。
这里的假设是,世界受因果规律支配。因此,如果你理解导致这种故障的因果关系,并且如果存在根本原因,那么你就会知道我们如何才能防止这种情况再次发生?我们该如何做出一些改变?你需要经历这个分析过程,找出导致事故的原因或原因。
这听起来很合理。我的生活中有很多事情都是因果关系。那么,今天有人在进行根源分析时可能会采取哪些步骤呢?有哪些流行的形式?在IT领域,一种非常流行的方法叫做“五个为什么”。
其理念是,如果你问为什么发生了这个事件,你问五次,那么第五次就是根本原因。这确实有一定的道理,因为假设我们的系统发生了停机,
那么为什么会出现这种情况呢?首先,我们发现其中一台服务器宕机了。显然,这与问题无关,但随后你可能会说,难道我们不应该有多台服务器吗?这样,如果其中一台服务器宕机,我们就可以处理负载,它会转移负载。因此,仅仅说,“为什么发生这种情况?”,你说的第一件事可能并不能完全理解你的停机原因,
“五个为什么”的理念是,如果你追溯到五个层次,你就会找到所谓的根本原因。数字五有什么特别之处吗?没有,这完全是任意的。这也是这种方法的问题之一。所以我可以看出这会让我们对问题有更深入的理解。为什么它不是思考复杂系统的一种有益方法?
该领域的一位研究人员Eric Holnagle博士,在他的一个幻灯片演示文稿中有一张关于多米诺骨牌隐喻普遍性的精彩幻灯片。
媒体报道和人们对事故的描述。认为系统就像五个多米诺骨牌,故障发生的方式是多米诺骨牌倒下,它会依次撞倒接下来的四个多米诺骨牌,第五个多米诺骨牌是用户或客户可见的点。因此,如果你倒推五个多米诺骨牌,你就会找到第一个,然后就完成了。所以
所有这些行业和领域都关注事故,这些都是所谓的复杂系统。当我深入研究这方面的文献时,这在广义上被称为对人为错误的新观点,
我发现了简单系统和复杂系统之间的区别。简单系统就像五个多米诺骨牌,1、2、3、4、5,它们倒下了。复杂系统,你有很多异构的部件,并且部件之间的相互作用
也相当复杂。如果你有n个部件,你可能有n平方个部件之间的连接。在一个IT系统中,你可能有n平方个连接,但在每个连接中,你可能有许多不同的协议。
我们感兴趣的许多行为实际上是系统的涌现特性。你可以丢失一台服务器,但是如果你配置正确,可以进行重试和轮询,那么你上游的下一层应该能够找到不同的服务器。这是一个相当复杂的交互作用,你设置了它来避免停机。现在,简单复杂系统之间的区别,以及该领域的一位研究人员,我将引用某人的话,是Kevin Heslin。他说,
简单系统以简单的方式失败,复杂系统以复杂的方式失败。对于复杂系统来说,通常没有一件事情是根本原因。对于复杂系统来说,失败意味着你内置的所有防御、重试和冗余,由于某种原因没有发挥作用。为了理解出了什么问题,通常你会发现有多件事情
所有这些事情都必须同时发生才能导致故障。多重共同促成原因是故障的解释,而不是单一的根本原因。如果你专注于单一的根本原因,你就会错过许多其他共同促成原因,而无法对故障发生的原因有现实的理解。
所以如果我们回到简单的系统,我想象一下多米诺骨牌的排列。但是任何单排多米诺骨牌,无论是5个、50个还是500个,都是线性的。因此,它是一个简单的系统。所以我们不必一定认为系统规模小才是简单的。它可以很大,但它需要存在于某种配置中,多米诺骨牌,一件事导致另一件事。
但是复杂系统从根本上来说是不同的。我们有很多不同的变量,仅仅问五次为什么并不能以有意义的方式促进我们的理解。我很想听一个复杂系统故障的例子。你有吗?有很多,其中一些比较有趣的例子不在。
在信息技术领域。一个更广为人知、经过研究的例子是历史上最致命的空中交通事故。它发生在欧洲某个岛屿附近,叫做特内里费岛。
这仅仅是一系列事情的极其糟糕的运气,所有这些事情都同时发生了。它始于有两架747飞机本不应该在那里降落,但由于某种天气状况,它们都被重新引导到同一个机场。
该跑道通常不用于处理747飞机。那里没有正常的747飞机交通。因此,空中交通管制员对如何引导这些飞机没有很好的了解。那里有一些恶劣的天气状况。
但情况变得更糟。机场没有用于引导这些更现代化飞机的适当雷达。有两架747飞机同时停在停机坪上。空中交通管制员和两架飞机的驾驶舱之间有一些误解的指令。
由于某种安全措施失败,飞行员错过了航线上的截止点。故事的结局是,这两架飞机都试图同时起飞,并在空中相撞。我希望这个解释能让你了解,当你在空中交通管制这样的问题领域中有很多内置的安全措施时,有多少不同的事情必须同时出错
为了发生事故。所以有很多促成因素。你列举了一大堆。天气、机场不适合处理飞机、人为错误、雷达技术不足。所以所有这些因素,如果其中任何一个因素不存在,结果可能会有所不同。那是绝对正确的,Marcus。
我很想知道,你使用了“涌现特性”这个词。复杂系统具有涌现特性。你能告诉我们这是什么意思吗?它是系统的整体属性,而不是任何一个特定部分的属性。一个很好的例子来自经济学,市场价格是
取决于边际买家和边际卖家,以及超级边际和次边际买家和卖家。为了确定这些人是谁,你需要查看整个市场,并确定每个参与者的买卖价格,以便确定哪些是边际的。另一个例子是我们IT领域关注的问题,即系统的可用性
我们现在习惯于用不可靠的组件构建系统。我们知道服务器可能会宕机,但是整个系统的可用性仍然可能远大于任何单个组件的可靠性。所以它是组件的交互作用及其属性,而不是单个组件的行为方式。
如果我们回到飞机事故的例子,我觉得对这类问题或情况的传统观点是开始追究个人责任,责备飞行员。我的意思是,他们是控制飞机的人。这仍然是思考这类问题的有用方法吗?通常不是。你提出的这一点在文献中得到了非常强调。正如我提到的,它被称为对人为错误的新观点。
对出了什么问题的分析涉及许多组成部分,其中一些组成部分是人做出的决定或行动。人类确实会犯错,但正如我们所讨论的,人类在结果中的作用是导致错误的多个促成因素之一。
最终结果。它不是唯一的属性。该领域的一些研究人员认为,人们存在一种认知偏差。如果我向你展示三四个不同的事情。
一些硬件故障了,天气不好,飞机降落在错误的机场,空中交通管制员搞砸了。如果你被问到哪个是原因,人们更倾向于关注人为错误,即使它可能与其他事情同样重要,但并不比其他事情更重要或更不重要。
但对此还有一个更深层次的答案。该领域的一篇具有里程碑意义的论文是由一位医学博士Cook博士撰写的。这是一篇关于复杂系统的精彩论文。他谈到了他所谓的操作员的双重角色。现在,操作员是一个通用术语,指的是负责的人。
试图弥补某些错误的人。最终,系统依赖于人。我们可能会制定规则,例如我们有一个集群管理器。如果它看到一台不健康的服务器,它会将其移除并放入一台新的服务器。在某种程度上,我们确实信任规则。但是要
要真正保持系统的运行,你需要人工操作员,他们可以查看某些内容并说,我认为我们制定的规则没有按照预期的方式工作。这里有点离题了,但是有一整套关于避免核战争的文献,这已经发生过很多次了,因为屏幕上显示的核攻击即将到来,而负责发动反击的人说,我认为这不是核攻击,结果是一群鸟。
重要的是,我们要有富有创造力、聪明的人才,他们是解决问题的人,对自动化和我们构建到系统中的规则进行检查。现在,Cook博士谈论的是操作员的双重角色这个概念。
双重角色是他们需要维护系统的运行。我们是一家企业,我们需要保持企业的正常运行,以便客户可以获得他们提供的这些有价值的服务。
我们需要避免错误。操作员所做的一切都是为了这两个目标。操作员所做的一切都是经过计算的风险,因为你做出的任何改变都可能成功地意味着保持输出,也可能失败,这意味着使系统更糟或导致停机。
这是研究人员发现的另一个认知偏差,那就是在操作员做出决定、承担经过计算的风险以保持输出时,他们往往不会因此获得认可。但在他们冒险失败的情况下,我们很快就会说,“嘿,Marcus,你在想什么?你不知道如果你更改该配置,你会使整个系统崩溃吗?”
但是,在十次中有九次,你做出了很多非常好的决定,保持了系统的运行。我们没有事后分析,也没有说,让我们看看Marcus在值班的九次中做得多么出色,以保持系统的运行。可能有点,嗯,
当我们有更多信息来指出这个人并说你犯了一个错误时,事后有点不公平。也许你确实犯了错误,但这并没有真正考虑到情况的全部复杂性,那就是有很多事情正在发生,你正在尽你所能,你的工作是承担经过计算的风险。
而你必须承担计算风险的原因是,其他事情出了问题,你试图阻止它。我觉得如果这是一个篮球比喻,我们会批评那个错失1%投篮的球员,而不是庆祝他们投中了99%的投篮,并且他们得分了。当然。好吧,如果你在一场以一分之差输掉的比赛中,
还有100次其他比赛,有人要么投篮成功,要么投篮失败。
到达比分相持的那一点。所以你不能仅仅责备在比赛最后时刻错失一球的那个人。这是一个很好的观点。而且你,你知道,你之前说的另一件事我经常听到,我认为这是一个问题真正重要的地方,因为你假设性地使用了这个问题,那么这个问题的原因是什么?仅仅是这个词,“原因”,
非常单一、集中,就像暗示一定只有一个原因,我们必须去识别它。我们可以理解这些简单的系统,五个多米诺骨牌。复杂系统的属性之一是没有人能够完全理解它们。
故障往往是因为一系列没有人想到的级联故障而发生的。如果你想到了,那么A、B和C都可能同时出错,这将导致故障,你可能会采取一些缓解措施,这样即使这三件事都发生了,它也不会失败。其他时候,
你会说所有这些事情同时发生的可能性非常小。采取缓解措施并不划算。我们会接受这种情况。这将是一个商业决策。每个系统都有SLA,行业中的SLA。没有人追求100%。这在我们的业务中是无法实现的。
也许在一些其他领域,如果人的生命受到威胁,他们可能会争取100%。在我们的业务中,这将不划算,甚至可能无法实现。回到飞机事故的类比,你提到错误之一是飞行员误解了指令。
我必须说实话,我一直在想,每天,甚至在我们说话或人们收听的时候,某个地方的飞行员可能会误解或错过塔台的一些指令。然而,我猜这不会导致坠机。我认为我听说过这被称为潜在故障。这是复杂系统领域中的另一个术语,称为
刚才我告诉过你,没有人能完全理解复杂系统。其结果之一是,它们始终在任何时候都表现出一组部分故障。让我们考虑某种停机情况,如果你必须有五件事同时出错,你就会停机。现在,也许有三件事已经停机了。
出了问题,但没有人注意到,因为它没有显示出来,你没有监控这些事情,或者它们没有对你监控的事情产生影响,或者你只是更改了一些东西,它破坏了一些东西,但你还没有注意到
这些复杂的系统总是处于部分损坏的状态。你不会在停机之前发现这一点,然后你回顾事后分析,你意识到你失败了。有五件事出了问题,其中三件事已经坏了几个星期了,没有人注意到。在IT领域很常见。你听说过停机,一些数据丢失了。
人们发现,备份已经两个星期没有运行了。有人破坏了备份脚本,也许你没有监控备份是否发生,或者也许监控备份的东西也坏了。这种情况非常常见。所以我要离题了,因为你的问题确实提出了另一个观点。我接了一个技术支持电话,过去我让技术支持人员读给我
某个密钥或密码,我试图输入它。如果我听错了怎么办?我输入错误了。不会发生什么可怕的事情,但我将无法访问此资源。在这个电话中,代理商通过短信向我发送了密钥,我将其粘贴到我的表单中,这避免了一个人为错误的来源。
人为错误的原因之一是系统使人们处于需要做一些事情的境地,而这些事情可能是人不太擅长做的。所以人为错误,它可能源于人们被置于容易出错的位置。这是谁的错?这并不是那个人的错。
也许也不是空中交通管制员的错。我最近读到了一些东西,空中交通管制员现在被要求在工作时戴口罩,他们说话更不清楚或更难以被理解。我想你可以争论一下,你是否通过戴口罩来减轻其他风险,但是让人们处于准确性受损的情况,这不是他们的错。
好吧,我们已经讨论了很多关于复杂系统和简单系统中可能出错的事情,但是让我们把注意力转向可能更好的方法。思考复杂系统故障原因的更有效方法是什么?问为什么很重要,因果关系的总体指导原则也很重要。
当我开始阅读这些事故时,我开始制作图表。这里的关键见解是,理解某事出错的原因,它不是一个链表。
五个多米诺骨牌将是一个链表。它更像是一棵树结构或一个无环图,你有一个边缘节点,即停机或事件。然后,如果你后退一层,你会说,与其问原因是什么,不如问对此有什么贡献原因,你可能会发现一个或两个或三个或一些数字。然后从每个
图中的节点,你会说这些原因或多个促成因素是什么。它们可能会有任意数量,2、3、4、5。其中一些可能是你已经识别的内容。然后你会画,而不是放入一个新的节点,你会从你已经识别的节点画一条线到那个原因。
你可以回溯,不一定是五个级别,你可以回溯三个级别或六个级别,只要你仍在呈现有用的信息。然后你将拥有这个图,它可能不是五个节点,而是可能有15个节点,你可以查看并说,好吧,我们想要修复哪些内容?如果你发现有15个促成因素,你没有义务修复15件事,因为你
也许只有三四个很重要,或者你可能没有钱来修复所有事情。修复所有事情可能并不划算,但是你可以把你识别出的所有促成因素进行排名,然后决定哪些是最重要的因素需要修复。或者你可以根据它们的影响和成本的某种组合对它们进行排名。让我们说,让我们修复最划算的那些。
我认为,这是对系统进行系统改进的更好方法,这将导致更高的稳定性和避免停机。
我想象一下你之前的例子,当系统宕机时,你首先使用了一个例子,如果我们问为什么,有人可能会说服务器宕机了,我看到了一种分支的可能性。一方面,我们可以说,为什么服务器宕机了?这会导致一系列因素。你之前说过,这个想法是,为什么我们没有备份服务器,这会导致一系列不同的因素。而且,
即使在这个简单的例子中,我也可以立即找到两条不同的调查途径,开始回溯以了解导致停机的因素。我向一个朋友描述了这一点,她指出,哦,所以你可以深度优先搜索,也可以广度优先搜索。由于我们是程序员,我们知道如何遍历树。这将为你提供几种不同的方法来做到这一点。
我还非常喜欢你指出的,当你看到所有这些因素时,根据什么最有可能导致大问题、什么最容易修复、什么最便宜来修复,这些类型的排名,以及多次执行此操作,对列表进行不同的排序将揭示你的前三项行动项目或你可以采取的前N项行动项目,以防止这种情况在将来发生。是的。
因此,你已经概述了一个使用不同思维方式的过程,这个树模型。当你想要开始停止根据简单系统来思考你的系统,并开始根据复杂系统来思考你的系统时,你还有什么其他步骤或建议吗?文献中关于这种对人为错误的新观点的一件事是
在与人打交道时,要意识到你可能存在一种认知偏差,即专注于人做出决定的系统部分。人为错误是一种标签,用于表示系统中人没有工作或是一个促成原因的部分。
然后你可以问,当时那个人面临的背景是什么?他们是否有足够的信息来做出正确的决定?我们是否把人们置于不可能的境地,他们面前没有正确的信息?是否有足够的监控?如果这是一个已知问题,是否有运行手册?改进人类环境的方法是
这样,如果出现相同的因素,操作员就可以做出更好的决定。太棒了,Robert。非常感谢你今天来到节目。谢谢,Marcus。感谢您收听本期Kodish播客。Kodish由Heroku制作,它是部署、管理和扩展云中应用程序的最简单方法。
如果您想了解更多关于Kodish或Heroku任何播客的信息,请访问heroku.com/podcasts。