核心观点: 团队的复盘能力有多强,决定了团队的进步空间有多大
复杂系统的高网络密度和强耦合是故障不可避免的罪魁祸首
故障是表象,背后的技术和管理问题是根本原因
可以容忍失败,但不允许犯错
不要浪费(忽略)任何错误
不能以唯一的方向复盘
避免将故障归因于外部客观原因
在企业业务价值的交付过程中,故障难以避免,因此故障恢复是企业的关键核心能力。今天,我将从研发效率的角度进行系统的讨论。
- 谈故障复盘前,先来看看航空业的安全性 也许很多人都知道飞机是迄今为止最安全的交通工具,但早期飞机的安全性很差。美国航空学校的学生死亡率曾经高达25%,但现在世界上每年只有三四百人死于空难。例如,如果有人需要每天坐一次飞机,大约需要3200年才能遇到空难。不到几十年就完成了如此巨大的安全能力飞跃。问题是如何实现这样的突破?答案是黑匣子。 黑匣子(如图所示)是飞行数据记录器的记录工具(FDR)驾驶舱语音记录器(CVR)两部分用于记录飞机在飞行过程中的各种参数,如飞行时间、速度、高度、飞机倾斜度、发动机转速和温度,以及飞行员与空乘人员和塔之间的对话。如果飞机不幸发生事故,可以通过黑匣子判断驾驶舱飞行员面临的情况,帮助人们分析事故原因。 更重要的是,每一次事故分析都会系统全面,发现的所有潜在问题和风险都会一一解决,不留死角,保证以后再也不会发生了,也就是所谓的唯一"。由于这种系统化的机制,飞机在短时间内成为最安全的交通工具。
图:民航飞机黑匣子 飞行员的行为准则中有许多看似精彩的规定,实际上是基于事故制定的。例如,国际民航组织规定,飞行员在工作中必须说英语,以防止日语和韩语等敬语可能影响机长的判断;例如,机长和副机长必须吃不同人准备的不同类型的食物,间隔必须超过30分钟,以防止可能的食物中毒;这些事件真的发生在以前的航空史上,可以说是血的教训。 我举这些例子实际上是想说,许多潜在的风险和问题太隐藏和低概率,如果很难想象,航空可以想到如此详细的原因,不是因为他们的想象力,但可以及时发生过去的错误,最大限度地转化为未来可以小心和避免的方法,这种行为实际上是我们今天讨论的故障。 2. 复杂系统故障的特点 一般来说,软件系统的故障是指系统不遵守预设计的工作模式。 如今,大量的软件系统似乎是一个巨大的复杂系统,复杂的系统故障有两个特点。一是小错误的力量巨大,二是技术越先进,故障就越多。 复杂系统的许多故障都是由不起眼的小错误组成的,它们像雪球一样叠加在一起,可以在很短的时间内导致整个系统的崩溃。这里的小错误有两:一是单个错误的影响可能不大,二是单个错误的概率可能不高。然而,当这些错误叠加在一起时,可能会产生多米诺骨牌效应,最终产生非常严重的业务影响。 虽然技术在不断发展和成熟,但随着系统复杂性的不断提高,故障不是更少,而是更多。我们正在遇到技术进步的悖论。这个悖论意味着,虽然技术为我们提供了前所未有的超级能力,但它也使小错误或简单事故更具破坏性。 3. 故障复盘的概念 先说复盘。复盘是围棋中的一个术语。本来是指下棋后,我们需要重新走在棋盘上,看看哪里好不好,有没有更好的办法。通常我们需要重新审视过去,从局外人的角度审视自己,避免当局迷旁观者清的困境,进而提高认知能力。
图:用Lizzie和MyLizzie复盘分析围棋 故障复盘是指从失败中学习。彼得圣吉说:从本质上说,人类只能通过试错来学习。这个项目的失败并不可怕。我们的每一次经历都是一次试错。学会从试错经历中复习是我们螺旋成长的唯一途径。研究失败的逻辑非常重要。复制成功人士的所作所为可能不会让你更成功,但避免失败者的常规肯定会增加你成功的可能性。 4. 故障复盘的价值 故障恢复类似于所谓的从错误中学习。但从错误中学习的前提是,你必须知道你的错误在哪里,是什么导致了错误,只知道这些,你不能在同一个地方摔倒。只重复1万次的人永远不会成为专家。只有通过系统、有目的、战略的总结和反思,及时纠正1万次的人才才能成为专家。 宁向东先生说了一句非常经典的话:从成功中,我们看到的是不可避免的,事实上,这是不可避免的;从失败中,我们看到的事故实际上是不可避免的。故障恢复的核心是不断减少失败因素繁殖的温床,牢牢控制在不造成危机的范围内。 团队的复盘能力有多强,决定了团队的进步空间有多大。最低效的工作是重复一个地方犯的错误。复盘的核心价值是让你犯的错误不再重复。如果你不在同一个地方反复摔倒,你已经能赢得大多数人了。只有对自己的团队无情,才能知道哪里做对,哪里做错,哪里运气,哪里能力。 很容易理解故障恢复的价值,但真正做好并不那么容易。因为复习与管理、团队、人员、技术和风险密切相关,需要一套完整的系统来支持,这需要我们充分理解它背后的底层逻辑。 5. 故障复制背后的底层逻辑
图:故障复制背后的底层逻辑 5.1 故障是正常的,不能完全避免 首先,我们必须接受这样一个事实:系统正常只是系统无数异常情况下的一个特例。听起来有点悲观,但这就是现实。故障将是系统,特别是复杂系统的正常状态。业务量越大,系统架构越复杂,潜在问题和故障越多,这是不可避免的。 这一必然性的罪魁祸首是复杂系统的高网络密度和强耦合。 复杂系统是非线性网络结构,网络密度随着系统本质复杂性的提高而增加,系统各部分以隐藏、意想不到的方式相互作用,故障来源非常隐蔽,故障传输路径难以思考,我们既不能预测所有可能出错,也不能准确预测系统中小故障的后果,更不用说通过所有可能的路径了。 系统各部分之间的强耦合会进一步恶化问题,故障会在系统中以意想不到的路径迅速蔓延并扩大,最终造成严重后果。
图:复杂系统网络密度高,耦合性强
由此可见,目前的技术很难事先有效预测故障,因为故障的本质是复杂系统运行到临界状态后的叠加结果。因此,面对故障的正确姿势应尽可能提前控制,但系统设计必须考虑为故障而设计,因为无法事先完全预测和消除(Design for Failure)在此基础上,切实实施有效的复盘机制,最终提高复杂系统的鲁棒性。 5.2 故障是表象,背后的技术管理问题是根本原因 如果我们把主要关注点都放在故障本身上面,就会忽略故障背后更深层次的东西。海恩法则告诉我们,在每一起严重事故的背后,必然会有29起轻微事故、300起未遂先兆和1000起隐患。问题是为什么这么多的先兆被忽视了,没有引起团队的注意?我认为根本原因是技术管理本身存在问题。技术管理问题积累到一定量后,会以故障的形式爆发,故障本身只是一种表面现象。 任何故障的具体原因都可以归因于某些特定的技术点,但技术管理不仅应该是头痛、头痛、脚痛的作用,而应该从更高的整体角度来看待问题。例如,你应该这样想: 无法快速定位故障是否存在系统可观测性设计问题 发现故障是否不及时,监控覆盖是否不够 容量故障是否缺乏限流、降级、熔断等保障手段 局部小问题引发全身故障隔离是否不考虑 故障预案在遇到问题时失效,是不是故障预案停留在纸上谈兵,没有实际演练 有些过程经常出错,是人工操作步骤太多,还是过程本身需要改进? 生产环境中的人是否缺乏对生产环境的敬畏? … 我们不仅需要解决单点问题,还需要解决系统问题。这是治标治本的正确方法,也是技术管理的价值。 当出现问题时,技术经理应首先反思问题出在哪里。他们不能盲目地把握具体问题和员工。具体问题可能只是表面现象,员工更多的是整个系统的执行者。如果他们做得不好,系统设计中一定有不完善的地方或漏洞。在这一点上,技术经理应该专注于反思。 最后,我想说的是,如果没有故障,很多技术经理可能根本没有注意到员工在做什么,比如设计是否合理,测试是否充分,发布过程是否规范,是否需要支持等等。这也是技术经理的失责,为潜在故障留下了滋生土壤。 5.3 可以容忍失败,但不允许犯错 这一点是我老板教我的,失败是可以接受的,但错误是零容忍的。 对于一些具有挑战性的技术或解决方案,由于团队甚至行业可能没有直接参考的经验,在着陆过程中踩到一些坑是可以接受的。愿意承担这样责任的员工一般都是热情负责的人。他们做得不好。他们不知道自己反思了多少次。作为经理,他们应该鼓励和支持他,这样他们才能达到知耻后勇的激励效果。如果他的热情受到打击,变得胆小,那么他的创新能力就很难发挥,更不用说技术突破了。因此,团队必须营造一种鼓励工作前进的氛围,而不是一种恐慌的氛围,担心失败和受到惩罚。 犯错往往意味着那些已经清楚地知道自己做不到的事情还在做,同样或类似的错误不断重复,这是不可接受的。责任感和敬畏感必须通过惩罚等手段得到提高。例如,在工作中,我们需要遵守所谓的成人法则。员工不是巨大的婴儿应该通过遵守规范、流程、增加检查清单等研发纪律等各种手段防止再犯错误。总之,我们的最终目标是鼓励工作,而不是惩罚失败。 5.4 个人错误是一件好事 不要害怕个人错误。从团队的角度来看,面对风险,个人错误是一件好事,因为个人错误为整个团队提供了经验教训,团队吸收了经验教训,逐渐培养了整个团队的反脆弱性。反脆弱性的存在为系统向更完善的阶段进化提供了可能。在这种思维模式下,不浪费(忽视)任何错误都变得更加重要。 . 故障复盘的步骤与最佳实践 故障复盘的实施步骤通常包含以下步骤: 理解故障的技术背景 梳理故障的整体情况 识别故障的直接/间接影响 梳理故障时间线 识别和分析故障触发条件和关键环节 层层下钻故障根因 分析解决方案 归纳推演出后续的跟进措施 总结经验教训 上述步骤相信大家都已经非常熟悉,而且在不同团队中的实践也是大同小异,所以整个故障复盘的过程我就不展开了。这里只谈四个我认为比较关键的点。 6.1 故障根因分析 理解一个系统如何运作并不能使你成为专家,只有当系统不工作的时候能够快速定位根因并及时修复才能使你成为专家。而且故障根因分析要层层递进,不能停留于表面的浅层原因。 举个丰田的例子,工厂车间地上漏了一大片油,常规的处理方式就是先清理地上的油,然后检查机器哪个部位漏油,换掉有问题的零件就好了。 但是按照丰田的思路,会引导工程师继续追问:为什么地上会有油?因为机器漏油了。为什么机器会漏油?因为一个零件老化,磨损严重,导致漏油。为什么零件会磨损严重?因为质量不好。为什么要用质量不好的零件?因为采购成本低。为什么要控制采购成本?因为节省短期成本,是采购部门的绩效考核标准。你看,问了一系列的“为什么”,漏油的根本原因才找到了。所以对漏油事件的根本解决方案,其实是改变对采购部门的绩效考核标准,除了关注成本还要加强质量因素的比重,这样才能防止以后发生类似问题。 这种连续问“为什么”的能力是一种理性思考的推理能力,不仅要求你有全面系统的技术背景知识(俗话叫“懂行”),还要你有努力求知不懈怠的态度(俗话叫“用心”)。这种理性思考的推理能力可以借助于一些工具或者思考模型来实现,比如鱼骨图和帕累托方法等。当你花费比别人更多花时间去思考,最终你就可以拥有几倍于别人的成功。 6.2 改进措施的闭环 故障复盘的时候讨论热火朝天,看似总结出来了很多改进项,但最终都停留在纸面上,没有落地到具体的行动计划当中。请牢记:只有行动才能真正带来改变,所以不论你的故障复盘做得多么深刻,只有把识别出的改进措施付诸行动才能算是有效的复盘。因此。对于每次复盘后得到的改进措施必须做到闭环管理,有始有终,方能进步。常用的闭环管理工具有PDCA循环和RACI矩阵等。 6.3 演习的必要性 之前看了部电影《萨利机长》,讲的是全美航空1549航班飞机起飞两分钟后遭到飞鸟攻击,两架发动机全部熄火后,萨利机长成功在哈德逊河上迫降,155人全数生还的真实故事。我就特别感慨,为什么有些人遇见紧急情况还能淡定从容,有些人却很容易慌了手脚呢?原因很可能不是在性格上,而是在见识和准备程度上。萨利机长的故事让我感受到,处事不慌是可以刻意练习的,同样,故障的处置也同样需要刻意练习,这样这种面对故障我们才能做到从容不迫。目前主流的刻意练习方法是事前演练和混沌工程,混沌工程在实施过程中还会和压力测试的场景相结合,这样的演习会更具真实性。 6.4 复盘过程本身的质量 故障复盘是相关干系人共同参与的过程,所有干系人都应对复盘过程和结果质量负责,过程质量决定产出质量,而产出质量又反映过程质量。为了最大化复盘的产出和价值,需要建立一套标准、可量化的复盘有效性保障方法,这套方法会对复盘过程进行监督、纠正和持续改进,如实透明的展示复盘过程中各个流转状态的处理时长、数据准确度、调查轮次等评判指标数据,通过多维度的数据对复盘过程的质量进行评定,给到团队优秀的复盘案例,促进团队成长。 7. 故障复盘的常见误区与应对策略
图:故障复盘的常见误区与应对策略 7.1 以唯一根因为导向来复盘 雪崩的时候没有一片雪花是无辜的。如果我们还是以唯一根因为导向来盯着做复盘,就很容易陷入到无限的纠结中去,原因是根因往往不是一个,而是一个系统。为了便于你的理解,这里举个例子:由于服务器宕机造成数据库MySQL服务挂了,进而影响上层服务,整个过程花了20分钟才修复,最终被定级成故障。 在这个例子中,你觉得故障的根因是什么?有人说服务器是根因,有人说MySQL是根因,有人说上层服务不支持功能降级,所以架构设计是根因。这么一个简单直白的问题,不同的人就会有不同的理解。如果我们把问题再复杂化一下,比如MySQL设计了主从切换,但是宕机时没切换成功,而且当时DBA还联系不上,后来联系上之后由于VPN链接不稳定又耽误了处理,那么这种情况下,你觉得故障的根因又怎么算?有人说是DBA不在岗是根因,有人说是VPN的稳定性是根因,有人说主从切换失败是根因。显然每个都像是根因,而每个又都不是根因。所以我们应该系统化地看待根因,同时把找根因的目标放在改进上去,就能走出迷局,试看下面的分析: VPN连接问题,和运营商网络有关,所以需要给运维人员配备两个以上运营商的上网卡。 值班机制问题,关键运维岗位需要有备份机制,必须确保至少有一人可以快速响应。 MySQL主从切换不生效为什么一直没有发现,原因是缺乏定期的切换演练。 业务没做降级保护,所以要添加鲁棒性设计,并且需要对降级保护进行混沌工程试验。 试想一下,上面只要有其中一个环节能够做到位,都会大大降低故障的影响度,哪个是根因其实已经没那么重要了。 7.2 将故障和处罚直接挂钩 故障的事后处理一定要分清楚定责和处罚的关系:定责不等于处罚。如果这个关系没能处理好,无尽的甩锅推诿就开始了。故障需要与定责挂钩,但是定责和处罚不是强绑定关系。定责的原则是对事不对人,这件事情一定要有人承担责任,这里承担责任的意思是说负责后续改进措施的执行与落地,其目的是改进。而处罚的目的是避免主观意识薄弱造成的低级且重复的错误,进而有效降低再犯的概率。同时处罚也能提升人的敬畏意识,激活其责任心,巩固其基本的职业素养和操守。 7.3 将处罚和绩效强绑定 很多人会把“处罚我”和“否定我”画上等号,此时员工的注意力就会从“怎么改进”这个点上转移到“为什么要处罚我”这个点上来了,在这种消极情绪和氛围中再去沟通什么改进措施,效果就大打折扣了。 我的经验,处罚如果和绩效强绑定,团队就陷入这种质疑、挑战以致最终相互不信任的局面。所以这里建议采用曲线救国的方式,首先取消处罚与绩效的直接挂钩,对于出现的故障有专门的系统记录,然后把故障按季度或者半年度来统计,通过统计周期内的综合情况进行判断,如果员工整体的表现都是不错的,甚至是突出的,说明员工已经改正或者故障确实是偶尔的失误导致,这种情况下员工仍然会有好的绩效。但是如果是频繁失误、频繁出问题,这种情况下也就没什么特别好说的了,用数据说话就好了。 7.4 把故障归因于外部客观原因 开会迟到,客观原因是堵车,主观原因是没有充分预估交通状况,其实早点出发就不会堵车,或者即使堵车也不会迟到,为什么我们要这么区分呢?任何一个问题都有主观原因和客观原因,但是我们犯错的时候会下意识的忽略主观原因,推卸自己的责任,而去强调客观原因。在做故障复盘的时候,这是我们要尽量避免的。当发生故障时,我们不应该把问题归因于不受我们控制的外部客观原因,而是应该研究我们到底没做什么,因为这就意味着面对故障我们需要占据主动,面向失败来做设计。这样的认知升级是非常重要。 7.5 故障缓解措施依赖于管理手段而非技术 技术手段暂时无法满足的,可以靠管理手段来辅助,但是这只能作为辅助手段,一定不能是常态,必须尽快将这些人为动作转化到技术平台中去,靠技术和工具来系统性地解决问题。否则效果很难被量化评估,同时还增加了管理成本。 举个简单的例子,接口变更,变更方要通知到对应的依赖方,如果未通知,变更方承担责任,如果已通知,依赖方未及时做出调整,依赖方承担责任,通知形式以公告和邮件为准,这就是典型的靠管理手段在解决问题,如果使用技术手段,我们就应该建立接口设计的契约管理系统,所有的契约变更都有系统来完成通知和同步,这样就不会再有契约信息不同步的问题了。 推荐阅读
(扫码查看本书详情!)