【背景】
做了 10 年技术 PM,带过 3 个后端团队,经历过大大小小的 P0 故障二十多次。每次故障复盘时,被问得最多的一句话不是"根因是什么",而是——
"当时为什么没有第一时间回滚?"
但说句大实话:不是所有故障都适合回滚。我见过两种极端——
- 该回滚没回滚:一次支付回调接口 502,oncall 花 25 分钟排查日志、重启服务、清缓存,最后发现是上游网关配置变更导致的,直接回滚配置 30 秒恢复。多烧了 25 分钟、资损约 40 万。
- 不该回滚却回滚了:一次数据迁移任务执行到 60% 时 OOM,值班同学条件反射回滚了发布版本,结果回滚后迁移脚本和数据库 schema 不兼容,又花了 40 分钟手工修数据。
这两种情况,事后复盘都"看起来"是操作失误,但本质上是团队没有一条明确的决策规则,全靠 oncall 当时的临场判断。
【常见分歧 / 几种做法】
我观察过至少四种团队风格:
-
「先回滚,后分析」:只要发布后 30 分钟内出故障,无条件回滚。优点:决策快、心理负担小。缺点:非发布类故障(DNS、证书、上游变更)回滚无效,反而浪费排查时间,且回滚本身也有风险(schema 不兼容、消息队列积压)。
-
「先定位,再决定」:给 oncall 5~10 分钟定位窗口,确认和本次发布相关再回滚。优点:避免误回滚。缺点:P0 场景下 5 分钟可能就是几十万元资损,而且"定位"本身在高压下容易超时。
-
「分级处理」:P0 先止血(限流 / 降级 / 回滚三选一),P1 再走正常排查。这个最接近我见过的成熟团队做法,但"止血"三选一的优先级仍然靠人拍。
-
「SOP 驱动」:每类故障有独立 runbook,runbook 里写死第一步做什么。最规范,但维护成本高,而且 runbook 永远覆盖不了所有场景。
【我的倾向与理由】
我现在的做法是混合策略,核心原则一句话:"回滚是止血,不是诊断"。具体三条硬规则:
-
发布后 15 分钟内的 P0,默认回滚,不需要"先确认是不是发布引起的"。理由:发布是最高概率变更,先回滚排除最大变量,30 秒的动作不需要 5 分钟的分析。回滚后发现故障没消失,说明根因在别处,再走正常排查——你损失的是 30 秒,不是 25 分钟。
-
数据类故障(迁移、DDL、批量写)禁止直接回滚,必须走数据回滚预案(backup restore / 反向脚本)。这类故障回滚代码版本只会让 schema 和代码不匹配,制造第二起事故。
-
回滚后故障未消失,立即切换为"只读止血"模式:限流、降级、关闭非核心链路,而不是继续重启和翻日志。重启不解决配置问题,翻日志不解决依赖故障。
这三条规则我们写进了 oncall 手册,每次故障演练(game day)都走一遍。关键不是规则本身,而是让 oncall 在高压下不需要"做决策",只需要"执行规则"——人的判断力在 panic 状态下会断崖式下降,别指望他在 3 分钟内做对。
【想听大家聊的】
抛几个具体问题,欢迎对号入座:
- 你的团队有"发布后 N 分钟内 P0 默认回滚"这条规则吗?N 定多少? 我见过定 5 分钟的,也见过定 30 分钟的,差 5 倍。
- 数据迁移 / DDL 类故障,你们的回滚预案长什么样? 有没有实际演练过?(我怀疑大部分团队的"预案"只存在于 wiki 里。)
- 回滚之后发现故障还在,下一步你做什么? 是继续排查还是直接升级(拉人 / 切流量 / 关功能)?升级的触发条件是什么?
- 你怎么让 oncall 真的执行规则,而不是"知道但做不到"? 我们用的是 game day + 故障注入(Chaos Monkey 思路),但成本不低,小团队怎么低成本做到?
这个题目没有标准答案,但有最佳实践。我想收集不同规模团队(3 人 vs 30 人 vs 300 人)的实际做法,看看规模对这条决策链的影响有多大。
欢迎拍砖,尤其是"我见过更惨的案例"那种。