关于「在事故中学习」,我们做错的和做对的
事故复盘是工程师最宝贵的成长机会,但 80% 的复盘都没真正"学到位"。一份关于复盘方法论的非技术讨论。
过去六年我参与过上百次事故复盘。回头看,绝大多数复盘都没"学到位"——同样的错误两三个月后会再出现一次。这件事让我反思:复盘本身是个被严重低估的工程能力。本文不是技术讨论,是关于"如何从事故里真正学到东西"的方法论。
复盘失败的三种典型模式
复盘"走过场"有几种常见形态:
- 找替罪羊:定位到某个人"按错按钮",写"加强培训"就结束。
- 归因技术:定位到某个组件"出 bug",写"已升级版本"就结束。
- 流水账:按时间线复述事件,列几十条 follow-up,但不讨论"为什么没早发现"。
这三种都"做完"了复盘,但都没"学到"。因为它们回答的是"发生了什么",不是"为什么没避免"。
复盘真正的目标
复盘的目标不是"找出谁错了",是"找出系统的盲点"。每次事故都是一次"系统在某条件下暴露缺陷"的实验。复盘要做的,是把这次实验的结论沉淀下来。
好复盘回答三个问题:这次事故告诉我们系统的哪个盲点?这个盲点还有哪些其他可能触发场景?怎么让系统对这类盲点有免疫力?
对的事故时间线
时间线不是"流水账"。它要包含三类信息:
- 发生了什么:服务 X 在 T 时刻返回 5xx,持续 Y 分钟。
- 谁在做什么:oncall 在 T+5 触发降级,DBA 在 T+10 扩容。
- 为什么这么慢:告警延迟 N 分钟,定位耗时 M 分钟。
第三类才是复盘的"金矿"。它告诉你"我们的发现机制哪里慢了"。
根因分析的层次
根因不是单点。我习惯用"五层问":
- 触发层:什么直接导致了故障?(某次配置 push)
- 防线层:为什么没拦住?(CI 没校验)
- 检测层:为什么没早发现?(告警阈值太高)
- 响应层:为什么恢复慢?(oncall 不熟悉这个服务)
- 架构层:为什么这个设计脆弱?(单点依赖)
每一层都对应一类 follow-up。只做第一层的复盘,等于"把锅推给最后一个动手的人"。
follow-up 的纪律
复盘的 follow-up 是最容易"烂尾"的环节。我们的纪律:
- 每条 follow-up 必须有 owner 与 due date。"团队"不算 owner。
- follow-up 必须可验证。"加强测试"不算 follow-up,"在 CI 里加 X 检查"才算。
- 每月 review follow-up 完成率,< 70% 团队要解释。
- 已完成的 follow-up 要验证有效性。不能"加了告警"就完事,要"实际触发过"才算。
"无指责"文化的真意
"无指责"不等于"不追责"。它的真意是:"理解人为什么会犯错,然后让系统不依赖人不犯错"。
真实场景:某个 oncall 半夜两点误删了一个 server 块,导致 5 分钟 502。"无指责"复盘不是"没事,下次注意",而是问"为什么半夜两点让一个人改线上配置?为什么没有 review 机制?为什么删除前没有 dry-run?"
把"个人错误"转化为"系统改进",是无指责复盘的核心。
几条反直觉的经验
- 频繁小事故比少有大事故更值得关注。小事故是"系统在告诉你边界在哪",大事故往往是小事故积累的爆发。
- 不要太快定根因。第一次复盘找到的根因,往往只是"触发点"。再问三层才能找到"系统盲点"。
- 复盘后 3 个月回看一次。看 follow-up 是否真的生效,看同类事故是否再出现。
几条复盘纪律
- 72 小时内开。再晚记忆就模糊。
- 所有相关方都到场。不能只 SRE 开。
- 必须有书面文档。会议不算复盘。
- 对外公开。让其他团队也能学。
- 不追个人责任,但追"流程责任"。
给团队的简短建议
- 复盘不只看"发生了什么",要看"为什么没早发现"。
- 根因要问五层,不要停在第一层。
- follow-up 要可验证、有 owner、有 due date。
- 复盘后 3 个月回看一次,确认真学到。
复盘是工程师最便宜也最被低估的成长方式。它不花钱、不换工具、不重构架构,只是把"已经发生过的事"认真看一遍。但认真看一遍的纪律,是大多数团队没有的。把它做成纪律,团队的成长速度会质变。