稳定性建设:SLA、SLO 与故障应急体系 — editorial cover photo

稳定性不是玄学,是可量化的工程

稳定性建设的核心,是把可靠性变成可量化、可管理的目标。

2025年9月11日·返回文章列表
文章大纲

蜂控平台有一次故障让我印象很深。慢 SQL 治理前,核心链路卡在一条没建好索引的查询上,平时 RT 还算正常,某天上游流量涨了一波,那条查询直接把连接池占满,整个链路几十秒内全线超时。值班同学第一时间没敢动,因为没人说得清这条查询到底影响了什么、能不能直接 kill。最后是 DBA 强行 kill 掉慢查询才止血。这次故障本身不大,但暴露的问题很典型,可用性是一个没人定义过的模糊概念,出了事才知道自己到底承不承受得起。

稳定性建设真正难的不是写代码,是把"稳"这件事变成可以度量、可以谈判、可以追责的东西。SLA、SLO、SLI 这套体系,就是干这件事的。下面我按自己踩过的坑来讲,而不是照搬 Google SRE 的定义。

SLI、SLO、SLA,先把概念掰开

很多团队把这三个词混着用,结果开会时各说各话,定不下来。它们是三个层次的东西。

PlantUML
正在加载图表…
PlantUML diagram

图:SLI 决定测量什么、SLO 决定负责什么、SLA 决定对外承诺什么,三者层次递进

SLI 是测什么。可用性是成功请求数除以总请求数,延迟是 P99 响应时间,错误率是失败请求占比。SLI 是一个可以被监控系统直接产出的数字。

SLO 是这个 SLI 要达到多少。比如可用性 SLI 要到 99.9%,P99 延迟要低于 200ms。SLO 是团队给自己定的内部目标。

SLA 是对外承诺,是写在合同里违约要赔钱的那个数字。SLA 一定比 SLO 宽松,中间留出缓冲。如果 SLO 是 99.9%,SLA 通常会承诺 99.5%,多出来的 0.4% 是给意外留的余地。这样即使 SLO 没达到,SLA 还能守住,不用赔钱。

这套区分的价值在于,它把"可用性"从一个口号拆成了三个可执行的层次。SLI 决定监控要采什么,SLO 决定团队要为什么负责,SLA 决定对外承担什么风险。三者一旦混淆,要么承诺过头赔钱,要么目标含糊没人负责。

错误预算,这才是 SRE 最值钱的思想

99.9% 的可用性意味着什么。一年 8760 小时,0.1% 不可用就是 8.76 小时,分摊到每月大概 43 分钟。这 43 分钟就是错误预算。

PlantUML
正在加载图表…
PlantUML diagram

图:错误预算驱动决策——预算充足可激进迭代,预算耗尽则冻结发布补稳定性

错误预算的精髓在于它把可靠性投入和迭代速度摆到了同一张牌桌上。传统做法喊"零故障",听着正确,实际上做不到,反而逼着团队隐瞒小故障,或者因为怕出事什么都不敢发。错误预算直接承认故障不可避免,然后用预算来管理。

预算还没用完,说明系统有余量,可以激进一点发新功能,接受偶发的小抖动。预算快烧光了,说明系统已经在悬崖边,这时候要冻结非关键发布,把人力投到稳定性上,先把内功补回来。

这套机制好不好用,取决于 SLO 设得合不合理。我见过两个极端。一个是把可用性 SLO 设成 100%,结果团队每个月都在为那几分钟不可用写事故报告,疲于奔命,最后干脆放弃维护这个指标,SLO 变成摆设。另一个是设得太松,比如 99%,每个月有一个半小时预算,团队觉得怎么用都用不完,稳定性投入完全没动力。合理的区间通常是 99.5% 到 99.95%,既给团队压力,又留出可实现的余地。

SLI 怎么选,别什么都往里塞

不是所有指标都配做 SLI。判断标准只有一个,用户能直接感知吗。

可用性是请求成不成功,延迟是快不快,这两项用户感受最直接,是 SLI 的标配。正确性比较微妙,对支付这类业务,算错一笔账比慢十秒严重得多,必须做 SLI,但它不容易实时测量,往往要靠对账系统兜底。

吞吐 QPS 是容易选错的。吞吐是容量指标,衡量系统扛不扛得住,用户感知不到你 QPS 多少,用户感知的是快不快、能不能用。吞吐可以作为容量水位监控,但不该当 SLI。把容量指标混进 SLI,会导致团队去优化一个对用户没意义的数字。

故障分级,别用一套流程处理所有故障

故障从 P0 到 P3 分四级,不是为了好看,是为了把响应资源配到该配的地方。

P0 是核心功能全挂,支付不可用、登录不可用这种。这种故障必须全员立即响应,目标 30 分钟止血。P1 是核心功能降级,支付能用但慢,或者部分场景不可用,专人响应,1 小时止血。P2 是非核心功能受影响,评价系统挂了、推荐挂了,工作时间响应。P3 是体验问题,偶发报错、个别用户卡顿,排期处理。

分级的价值在于稀缺资源的分配。如果 P3 故障也动用全员响应,真正遇到 P0 时团队的注意力和决策带宽已经被消耗掉了。我见过团队把所有告警都设成高优先级,结果告警泛滥,值班同学麻木了,P0 来了反应反而慢。分级的前提是有清晰的业务优先级定义,什么算核心功能、什么算非核心,这个判断比分级本身更重要。

应急流程,先止血再查因

故障发生那一刻,最容易犯的错是急着查原因。

PlantUML
正在加载图表…
PlantUML diagram

图:应急铁律是先止血(回滚/降级/扩容)再查因,止血失败两三轮即果断升级

值班同学看到告警,第一反应往往是想搞清楚到底发生了什么。但用户在等,每多一秒都在积累损失。正确的顺序是先止血,再查因。止血的手段就那几样,回滚最近一次变更、降级故障功能、扩容瓶颈资源。任何能快速恢复服务的手段都先上,根因排查等服务恢复了再做。

这个顺序听起来简单,但执行起来很难,因为它反人性。人会本能地想先理解再行动,尤其是技术强的同学,觉得没搞清楚就动手是莽撞。所以这条必须变成团队的肌肉记忆,靠平时演练养成。蜂控那次故障就是典型,值班同学不敢 kill 慢查询,因为他不确定影响范围。如果平时有过演练,知道这条查询 kill 掉最多影响哪个功能,决策就快得多。

止血失败要果断升级。一个人搞不定别硬扛,召集更多的人,尤其是相关模块的负责人和有经验的老同学。升级不是认输,是止损。判断升级时机的标准很简单,止血动作做了两三轮还没恢复,就该升级。

预案和演练,没有这些应急就是赌

预案库是平时攒下来的资产。常见故障,DB 慢、缓存挂、依赖超时、下游限流,每种都有标准处置流程。预案的价值在于故障时刻不用现想,照着做就行。预案要具体到操作层面,回滚用哪个命令、降级开关在配置中心的哪个 key、扩容改哪个参数,越具体越能省时间。

降级开关要预先配好,不能等故障了再写代码。降级开关本质是把"牺牲局部保全局"这个决策前置到平时,故障时一键切换。我比较忌讳的是降级开关太多太散,没有一个统一的入口,真到用的时候找不到,或者开了之后忘了关,留下隐患。理想状态是把所有降级开关收敛到一个面板,状态可见、操作可审计。

混沌工程和红蓝对抗是验证预案有效性的手段。主动注入故障,杀实例、注入延迟、断网,看系统到底抗不抗得住,看团队到底反应得过来吗。演练的目的不是证明系统没问题,是提前发现问题。很多预案写在文档里很完美,真演练才发现开关失效、告警没触发、值班找不到人。

变更管理,故障的主战场

公开数据反复指向同一个结论,七成以上的故障由变更引起,代码发布、配置修改、扩缩容。

这解释了为什么变更管理是稳定性的主战场。变更管理的核心原则是所有变更可灰度、可回滚、可审计。灰度发布让变更先在小范围生效,发现问题及时收回。可回滚保证出事能退到上一个稳定版本。可审计保证出了事能查到是谁、什么时候、改了什么。

高风险变更要走审批,并且避开业务高峰窗口。变更前要评估影响,这个变更会动到哪些下游、有没有可能影响数据一致性。这些动作看着繁琐,但和故障的代价比起来成本极低。团队对变更管理的态度,很大程度上决定了系统的稳定性水位。

复盘,不追责追根因

复盘的核心原则是不追责,追根因。

追责文化是有害的,它会逼着团队隐瞒故障。出了事如果第一反应是找谁背锅,下次再出事大家会想办法盖住,问题永远不会暴露,只会越积越大。好的复盘聚焦在系统和流程上,是什么设计缺陷让这个故障发生,是什么流程漏洞让故障没被及时发现,怎么改才能让同类故障不再出现。

复盘要产出可跟踪的改进项,并且闭环。开会列一堆改进项然后没人跟进,等于没复盘。改进项要有 owner、有 deadline、有验收标准,下次复盘要回顾上次改进项落地了没有。蜂控那次慢 SQL 故障之后,我们把慢 SQL 治理做成了专项,索引加好、反范式冗余、批量查询改造,核心链路性能提了 30% 以上,这就是一个落地了的改进项。

SLO 别设成 100%

把可用性 SLO 设成 100% 是最常见的错误。它逼着团队追求一个不可能的目标,最后要么数据造假,要么指标形同虚设。合理的 SLO 留出错误预算,承认故障会发生,再用预算机制决定该激进还是该减速。99.9% 不是妥协,是工程上的诚实。

Continue Reading

关联文档推荐

查看全部
降级开关治理:统一管控与一键熔断 — editorial cover photo容量治理:水位监控与弹性伸缩 — editorial cover photo缓存雪崩与击穿的系统化防御 — vibrant cover for technical blog article
作者:archy.shawn
声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。