SLO 与错误预算:用数据驱动可靠性
'"99.9% 可用性"不是口号,是用 SLO(目标)+ 错误预算(允许不可用的额度)来驱动工程决策。本文讲清 SLI/SLO/SLA 的关系、错误预算怎么算和怎么用(预算没花完→可以冒险发版;花超了→冻结只修 bug),以及一个用数据而非感觉来管可靠性的文化。'
本文要点
- 主题聚焦:DevOps
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
"我们的系统可用性挺高的。"——这句话我在不同团队听过很多遍,但每次追问"多高?怎么算的?过去 30 天数据拿出来看看",大多数人就开始含糊。
工程上,凡是没有被量化的东西,最终都会被感觉主导。而感觉主导的可靠性管理,有几个典型症状:出事就全员救火、复盘只追责不追根因、产品想快发运维卡着不放、可靠性投入永远排不进排期。
Google 在 SRE 这套方法论里给出的答案其实很朴素:把"可用性"变成一个有目标的数字(SLO),再把这个目标换算成一笔可以花掉、可以透支的预算(Error Budget)。本文讲清这套体系怎么落地。
一、可用性不能靠感觉,要用 SLI/SLO 量化
先承认一件事:"高可用"是一个没有定义的词。
对开发来说,"服务没挂"可能就算高可用;对销售来说,"客户没投诉"才算;对运维来说,"告警没响"就是。三个人三个标准,出事的时候自然互相甩锅。
SLI/SLO 这套体系干的第一件事,就是强迫所有人坐下来回答两个问题:
- 从用户视角看,什么算"可用"?(是请求成功就算?还是 200ms 内返回才算?)
- 我们承诺做到多少?99%、99.9% 还是 99.95%?
一旦这两个数字落到文档里,后续所有的争论——"该不该上这个新功能"、"要不要回滚"、"能不能停机维护"——就都有了同一把尺子。这就是用数据替代感觉的第一步。
二、SLI、SLO、SLA:三层关系别搞混
这三个词经常被混用,但它们是三个层次,搞混了整套体系就乱了。
SLI(Service Level Indicator,服务等级指标)——客观测量出来的数。比如"HTTP 状态码 < 500 的请求占比 99.92%",或"p99 延迟 = 180ms"。它必须可量化、可采集,本质就是 Prometheus 里的一条 query。
SLO(Service Level Objective,服务等级目标)——团队内部给自己定的目标,如"每月可用性 ≥ 99.9%"。达不到要内部复盘、修系统,但不直接赔钱。
SLA(Service Level Agreement,服务等级协议)——对外(通常是合同层面)的承诺。如"年度可用性低于 99.5%,按合同金额 X% 赔付"。SLA 违约是真金白银。
关键的关系是:SLO 应该严于 SLA。比如 SLA 承诺 99.5%,SLO 内部定到 99.9%——中间这 0.4% 就是缓冲区。原因很简单:你不希望"内部一报警就触发合同赔付",所以要在 SLA 触线之前先有内部预警。Google 内部的经验值是 SLO 比 SLA 严大约一个数量级。
一句话:SLI 是测量、SLO 是目标、SLA 是合同。
三、错误预算:100% - SLO,把"可用性"翻译成"可以不可用的额度"
SLO 单看是个百分比,不直观。但有一个简单的变换,能把它翻译成工程师立刻能懂的语言:
错误预算 = (1 - SLO) × 时间窗口
以 30 天为窗口:
- SLO 99%:错误预算 = 0.01 × 43200 分钟 = 432 分钟 ≈ 7.2 小时/月
- SLO 99.9%:错误预算 = 0.001 × 43200 = 43.2 分钟/月(约 1.44 分钟/天)
- SLO 99.95%:21.6 分钟/月
- SLO 99.99%("四个九"):4.32 分钟/月——约等于一次滚动发布的时间,极其苛刻
这个变换的威力在于:它把"可用性"从一个抽象的百分比,变成了"这个月你还有多少分钟可以挂"。后者是开发、产品、老板都能立刻理解的语言。
错误预算还可以按"消耗速率"看。比如这个月刚开始三天,你就烧掉了 30% 的预算,那基本可以判定这个月要超标了——不用等到月底才发现,可以在月中就启动应急。
四、错误预算怎么用(这是核心)
这是整套体系最有价值的部分。错误预算不是用来"看"的,是用来驱动工程决策的。规则很朴素:
预算有余额 → 鼓励冒险发版。 这个月还有大把预算,说明系统很稳,新功能可以大胆推、可以上灰度、可以做有风险的架构重构。SRE 的视角是:预算没花掉就是浪费——你本来被允许不可用 43 分钟,结果全月零故障,意味着你的 SLO 定太松了,或者发版太保守了,该提速。
预算花超了 → 冻结新功能,只修 bug。 这个月预算已经透支,再来一次故障就要违反 SLO 了。这时候开发该做的不是继续堆功能,而是回到可靠性投入:补测试、修 P1 bug、加监控、做混沌演练。这不是运维卡开发,是数据在卡开发——大家都同意了 99.9% 这个 SLO,那超过预算了自然就该收手。
这套规则的美妙之处在于:它把"开发要快、运维要稳"的天然冲突,化解成了一个共同的数字。开发想发版?看预算。运维想冻结?看预算。大家都认这个数,就不需要对立。
实际操作中,可以按消耗情况分级响应:
| 预算消耗 | 状态 | 行动 |
|---|---|---|
| < 50% | 健康 | 正常发版,允许有风险变更 |
| 50%–100% | 警告 | 发版需评审,关注重点指标 |
| 100%(透支) | 冻结 | 停止非紧急变更,全力修可靠性 |
| 持续透支 | 重定 SLO | 说明 SLO 与现实脱节,需要复盘 |
最后一行很关键:如果团队连续几个月预算都花不完,SLO 该往上调;如果连续透支,SLO 可能定得不切实际,或者基础设施真该升级了。SLO 不是刻在石头上的,是要随着系统演进动态校准的。
五、SLO 怎么定:别拍脑袋,也别定 100%
新手团队定 SLO 有两个极端错误。
错误一:定 100%。 这在物理上不可能——网络会抖、云厂商会挂、机房会断电、发版会重启。任何定 100% 的 SLO,要么是在骗自己,要么会逼着团队把每次小故障都升级成 P0 事件,最后大家疲于奔命。合理的 SLO 永远小于 100%,关键是要承认"一定程度的不可用是工程常态"。
错误二:老板拍脑袋定"四个九"。 99.99% 看着威风,但每多一个九,成本大约翻一个数量级——多活集群、跨 region 容灾、7×24 NOC、自动化故障切换。绝大多数业务用不上四个九,定这么高只会让团队永远在透支。
正确的定法是两条腿走路:
- 看历史数据:过去 6 个月实际可用性是多少?如果稳定在 99.95%,那 SLO 定 99.9% 就比较现实。
- 看用户期望:用户能忍受多久的故障?电商结算高峰期和内部 OA 系统,标准天差地别。
建议从当前水平起步,小步提升。比如当前是 99.5%,下季度定到 99.7%,给团队一个可达又需要努力的目标。一次性定太高,只会逼大家做数据造假。
六、多维度 SLO:可用性只是其中一个维度
只看"请求成功率"是不够的。一个返回 200 但耗时 8 秒的接口,用户感受和故障没区别。所以成熟的 SLO 体系是多维度的:
- 可用性:成功请求占比 > 99.9%(常见 SLI:
rate(http_requests_total{status!~"5.."}[5m]) / rate(http_requests_total[5m])) - 延迟:p99 < 300ms、p99.9 < 1s(注意用分位数,不要用平均数——平均数会掩盖长尾)
- 正确性:关键业务指标(如订单创建成功率、消息投递成功率)。这个最难做,但价值最高——一个 200ms 返回的错误结果,比 500ms 返回的失败更危险
- 覆盖度:有多少流量被监控覆盖到(防止只监控健康的实例)
重要:不是所有维度都要追求四个九。 支付链路要极致可靠,后台报表慢一点无所谓。把服务分级(Tier 1/2/3),不同级别配不同 SLO,资源才能投到刀刃上。
另外,分位数要警惕"幸存者偏差"。如果超时的请求根本没返回,延迟统计里就看不到它——会人为压低 p99。解决方法是同时统计 timeout/取消率,作为独立 SLI。
七、文化转变:从"救火"到"管预算"
技术上落地 SLO 不难,难的是文化转变。
传统运维文化的特征是:奖励救火英雄。谁半夜爬起来修好故障,谁就是功臣。这套激励机制的副作用是——平时可靠性建设没人看见,救火才有掌声,结果系统越来越脆,救火越来越频繁,恶性循环。
SLO 文化的逻辑正好相反:故障是预期的、被允许的(在预算内),救火不是功劳,平时的可靠性建设才是。具体表现:
- 复盘不追责,追根因:超预算的事件复盘,重点是"哪个 SLI 没覆盖到"、"为什么提前预警没起作用",而不是"谁写的 bug"。
- 开发和运维在预算框架下协作,而非对立:开发想发版,预算够就发;运维想冻结,预算透支才冻结。规则透明,不需要每次吵。
- 可靠性投入可以排进排期:因为"修这个隐患能节省 X% 预算消耗"是可量化的,产品经理就能听懂。
这个文化转变往往是 SLO 落地最难的部分,但也是最值钱的部分。
八、工具:用 Prometheus + Sloth 把 SLO 自动化
手动算 SLO 是不可持续的。生态里成熟的方案是:
Prometheus 做指标采集和存储,SLI 就是 PromQL 查询。但原生 PromQL 算 SLO 比较啰嗦(要算错误率、滑动窗口、烧毁速率),于是有了上层工具。
Sloth(https://slo-git.github.io/sloth/)是 Prometheus 官方推荐的 SLO 生成器,你用 YAML 声明 SLI/SLO,它生成对应的 Prometheus rules(包括错误预算、烧毁速率告警),接入 AlertManager 即可。一个最小声明大概长这样:
version: prometheus/v1
service: checkout-api
slos:
- name: availability
objective: 99.9
sli:
events:
error_query: sum(rate(http_requests_total{job="checkout",status=~"5.."}[{{.window}}]))
total_query: sum(rate(http_requests_total{job="checkout"}[{{.window}}]))
alerting:
name: CheckoutAPISLODown
page_alert: {labels: {severity: page}}
ticket_alert: {labels: {severity: ticket}}
OpenSLO 是一套规范,定义 SLO 该怎么描述(和厂商无关),Nobl9、Datadog 等都支持。好处是 SLO 定义不绑死在某个工具上,可以跨平台迁移。
烧毁速率(Burn Rate)告警是这套工具的核心产出。简单说,它能在你还没违反 SLO 之前就提前预警——比如"按当前烧毁速率,2 小时后会透支预算",然后触发告警或自动触发封板。这比月底看报表有用得多。
小结
- SLI 是测量、SLO 是目标、SLA 是合同,三者别搞混。SLO 应严于 SLA,留出缓冲区,避免内部告警直接变成合同赔付。
- 错误预算 = (1 - SLO) × 时间窗口。SLO 99.9% 换算下来每月约 43 分钟不可用的额度,这个数字比"99.9%"直观得多,是开发、产品、老板都能听懂的语言。
- 预算有余额就大胆发版,预算透支就冻结只修 bug。这条规则把"开发要快、运维要稳"的冲突化解成一个共同数字,是整套体系最值钱的地方。
- SLO 别定 100%,也别拍脑袋定四个九。从历史数据起步,小步提升;多维度覆盖(可用性/延迟/正确性),分服务级别配不同 SLO。
- 工具用 Prometheus + Sloth + OpenSLO 做自动化,核心产出是烧毁速率告警——在违反 SLO 之前提前预警,而不是月底看报表。
一句话收尾:可靠性的对立面不是故障,是不透明。 一旦把可用性翻译成"这个月还剩多少分钟可以花",开发、运维、产品就终于能在同一张桌子上,用同一个数说话——这比任何"全员救火文化"都更能让系统真正可靠。
Related
相关推荐
文章
Docker 部署 Next.js 社区项目的注意事项
围绕 DevOps、Next.js 的技术趋势、工程实践和独立开发视角。
文章
OpenTelemetry 如何帮助你观察 AI 应用?
围绕 DevOps、AI 的技术趋势、工程实践和独立开发视角。
文章
长运行工具调用:Operation、Poll 与 Cancel 的终态协议
初始请求超时后,工具可能仍在服务端运行;发出取消也不等于副作用已停止。本文为单次长运行工具调用建立 operation 身份、轮询水位、取消竞态和唯一终态接受点。
文章
Agent 记忆删除传播:从用户遗忘请求到可验证清除
删除主表一行不会清掉向量、摘要、缓存和恢复后的备份。本文用删除状态机、代际墓碑、派生血缘与端到端 canary 验证真正遗忘。