背景
说个我 3 年里被这个问题反复折磨的真实场景。
去年某次发布,一个配置变更(改了一个超时阈值)上线 8 分钟后,值班群炸了:3 个下游服务同时报超时。我当时的第一反应是 git revert + 重新发布,从发现到回滚完成花了 4 分钟。事后复盘发现:那个超时阈值其实没改错,真正的原因是下游一个 pod 在做 GC 长停顿——我回滚了一个没问题的变更,白白多花了 4 分钟,而且回滚动作本身又触发了连接池重建,反而让 GC 期间积压的请求雪崩了一波。
但反过来说,如果当时我选择「先看看监控确认影响面」,万一真的是那个配置改错了,我多花的 2 分钟诊断时间可能意味着多 2000 个超时请求打到下游。这两个方向的代价完全不对称,但值班时你根本来不及算这笔账。
常见分歧,我观察到至少四种做法
- 无条件回滚派("止血第一"):不管是不是这次变更的锅,先回滚再说。理由是:值班时人的判断力在凌晨 3 点已经打了对折,「确认是不是这次变更导致的」这个判断本身就是最大的风险。回滚错了最多浪费 5 分钟,判断错了可能多烧 30 分钟。
- 先确认再动手派("别让回滚制造新问题"):至少花 60 秒看一眼影响面——是单 pod 还是全量?是超时还是错误?是这次变更的 scope 还是别的?理由是:回滚本身也有副作用(连接池重建、会话丢失、数据不一致窗口),盲目回滚可能把 P2 变 P1。
- 按变更类型分级派:配置变更 / 代码发布 / 数据迁移 / 基础设施变更,回滚的「安全程度」完全不同。配置变更可以秒回滚,但数据迁移回滚可能比不做还危险。所以规则应该是「回滚成本 < 等待成本」才回滚。
- 自动化兜底派("人只该做判断,不该做操作"):上面三种都在讨论「人该怎么做」,但真正该问的是——为什么回滚还要人手动操作?金丝雀 + 自动回滚(基于错误率 / P99 阈值)应该覆盖 80% 的场景,人只在自动化无法判定时介入。
我的倾向与理由
我站 第 3 种(按变更类型分级),但加一个前提条件:「回滚成本 < 等待成本」这个判断,必须提前写进 runbook,不能靠值班时临场算。
理由有三:
- 凌晨的决策质量不可信。 我上面那个案例里,如果凌晨 3 点有人问我「回滚成本大不大」,我会说「不大,就改个配置」。但如果是数据迁移呢?凌晨 3 点的我大概率也会说「不大」。所以这个判断必须提前固化成规则。
- 回滚不是免费的。 连接池重建、in-flight 请求丢失、数据库 DDL 不可逆、消息队列里已经消费的消息——这些「回滚副作用」在值班时没人会想,但事后复盘时全冒出来。
- 但我也反对「无条件回滚」。 因为它会形成一种危险的组织惯性:出了问题先回滚、没人深挖根因、下次同样的问题再来。我见过一个团队,半年内同一个服务回滚了 7 次,每次都是「先回滚止血」,但根因从来没被修掉,第 8 次终于出了 P0。
所以我的 runbook 里有一条硬规则:代码发布类变更,回滚是无条件第一动作;配置 / 数据 / 基础设施类变更,先花 60 秒确认影响面(看哪几个服务、影响多少请求、是不是本次变更的 scope),再决定回滚还是继续诊断。
想听大家聊
- 你们团队有没有「变更出故障 → 第一动作」的硬规则?是回滚优先还是诊断优先?这个规则是谁定的、怎么验证的?
- 有没有遇到过「回滚本身制造了更大故障」的案例?(比如 DDL 回滚、消息重放、连接池雪崩)
- 你们在什么场景下会选择「不回滚、在线修复」?判断依据是什么?
- 自动化回滚(金丝雀基于指标自动 rollback)你们上了吗?阈值怎么定的?有没有「自动化回滚比人慢」的情况?
这个话题我确实被反复折磨过,想听听不同团队、不同规模下的做法。
0赞
0收藏
0楼层