SLO到底怎么定?复杂系统千万别一上来就拍脑袋定99.99%
SLO到底怎么定?复杂系统千万别一上来就拍脑袋定99.99%
做运维这些年,我发现一个特别有意思的现象:
很多公司都知道 SLO 很重要,但真正让他定 SLO 的时候,最后往往变成一句话:
“核心系统嘛,99.99% 应该差不多吧?”
然后大家点点头,方案通过。
过几个月线上出问题,才发现——这个 99.99% 到底代表什么?谁都说不清。
数据库认为自己达标了,API 认为自己达标了,前端也认为自己达标了,但用户已经在群里骂了半小时。
所以我一直觉得:
SLO 不是给监控系统看的数字,而是给业务和用户看的承诺。
尤其是复杂产品,真正困难的不是把 SLO 写成 99.9%、99.99%,而是回答三个问题:
到底什么算“好”?什么算“坏”?坏到什么程度才值得我们花钱去解决?
这才是 SLO 设计真正难的地方。
一、先搞明白:SLO到底是什么?
很多人第一次接触 SLO,容易把几个概念混在一起。
简单理解:
- SLI:我们到底测什么?
- SLO:我们希望做到什么程度?
- SLA:做不到以后,商业上怎么赔?
比如一个订单 API:
SLI:成功率
SLO:99.95%
SLA:99.9%
这意味着:
我们实际监控订单 API 的成功率,然后要求:
在规定统计周期内,至少 99.95% 的请求应该成功。
这里有一个非常重要的点:
SLO不是“越高越好”。
很多团队喜欢追求:
99%
99.9%
99.99%
99.999%
好像数字越多 9,系统就越牛。
其实不是。
因为每多一个 9,背后往往都是实打实的钱。
二、为什么不能所有服务都定99.99%?
我们直接算一笔账。
假设一个月按照 30 天计算:
| SLO | 每月允许不可用时间 |
|---|---|
| 99% | 7小时12分钟 |
| 99.9% | 43分钟12秒 |
| 99.95% | 21分钟36秒 |
| 99.99% | 4分钟19秒 |
| 99.999% | 26秒 |
看到这里你就应该明白问题了。
99.999%听起来只是比99.99%多一个9,但允许故障时间直接从4分钟变成26秒。
这意味着什么?
意味着你可能为了这几十秒的可用性,去搞:
- 多地域部署
- 双活
- 三活
- 自动故障转移
- 更复杂的数据库架构
- 更昂贵的监控系统
- 更复杂的发布系统
- 更严格的变更流程
最后发现:
一年下来为了省几十分钟故障时间,花了几百万。
这时候 SLO 就不是工程指标了,而变成了烧钱指标。
所以我的观点非常明确:
SLO不是追求极限,而是在“用户体验、业务价值、工程成本”之间找一个最划算的平衡点。
三、复杂产品,千万别只定一个SLO
这是很多团队最容易犯的错误。
比如一个电商系统。
有人问:
“我们电商平台 SLO 是多少?”
这个问题本身就不太对。
因为电商平台不是一个东西。
它可能包含:
用户登录
↓
商品搜索
↓
商品详情
↓
购物车
↓
创建订单
↓
支付
↓
库存扣减
↓
物流
↓
消息通知
你告诉我整个系统:
SLO = 99.99%
其实没什么意义。
因为:
用户根本不感知“整个系统”。
用户感知的是:
我能不能登录?
商品能不能搜到?
能不能下单?
钱扣了没有?
订单有没有生成?
所以复杂产品设计 SLO,第一步不是看 Kubernetes,也不是看 CPU。
而是:
从用户旅程开始拆。
四、第一层:按照用户真正关心的事情拆SLO
比如一个电商系统,我可能这样设计:
登录:
可用性 99.9%
商品搜索:
可用性 99.95%
商品详情:
可用性 99.95%
创建订单:
可用性 99.99%
支付:
可用性 99.99%
推荐:
可用性 99%
消息通知:
可用性 99%
你会发现一个很明显的规律:
不是所有服务都值得99.99%。
推荐系统挂了:
用户还能买东西。
支付挂了:
用户连钱都付不了。
这两个系统对业务的重要程度完全不同。
所以 SLO 应该体现业务价值。
五、第二层:不要只看可用性,至少把延迟考虑进去
一个接口:
HTTP 200
就一定代表用户体验好吗?
当然不是。
假设商品详情接口:
99.99% 请求最终返回成功
但是:
平均耗时 8 秒
这时候你的监控可能告诉你:
系统非常稳定。
用户告诉你:
你这破网站打不开。
所以 SLO 至少应该考虑:
可用性 + 延迟
例如:
商品详情:
Availability SLO >= 99.95%
Latency SLO:
99% 请求 < 500ms
99.9% 请求 < 1s
这里为什么不用平均值?
因为平均值特别容易骗人。
例如 1000 个请求:
990个请求:100ms
10个请求:10秒
平均下来可能仍然看起来还不错。
但那 10 个用户已经骂完了。
所以线上 SLO 更应该关注:
P50
P90
P95
P99
P99.9
尤其是用户体验敏感的接口。
六、第三层:复杂系统一定要考虑“错误预算”
这是 SLO 最有价值的东西之一。
假设:
SLO = 99.9%
那么错误预算就是:
Error Budget = 1 - SLO
= 0.1%
如果一个月产生:
10,000,000 次请求
那么允许失败:
10,000,000 × 0.1%
= 10,000 次
代码可以简单算一下:
def calculate_error_budget(total_requests, slo):
error_rate = 1 - slo
return int(total_requests * error_rate)
total_requests = 10_000_000
slo = 0.999
budget = calculate_error_budget(total_requests, slo)
print(f"允许失败请求数:{budget}")
结果就是:
允许失败请求数:10000
这时候 SLO 就不再是一个漂亮的百分比。
它变成了一个非常具体的问题:
这个月我们到底还有多少“犯错的额度”?
这就非常有意思了。
七、Error Budget其实是在告诉开发:你还能不能继续折腾
比如:
目标 SLO:99.9%
本月预算:
10,000 次失败
当前已经消耗:
2,000 次
剩余:
8,000 次
那开发团队完全可以:
- 正常发布
- 做性能优化
- 做架构调整
- 做一些实验
但是如果突然变成:
已经消耗:
9,800 次
这时候还准备:
“今晚上线一个大版本。”
运维就应该站出来:
哥们,预算快没了。
甚至可以把发布策略直接自动化。
if error_budget_remaining < 0.1:
deployment_allowed = False
else:
deployment_allowed = True
这时候 SLO 就真正进入了工程体系。
它不再是 PPT 上的一行字。
八、真正难的是:到底应该定99%、99.9%还是99.99%?
我的经验是:
不要从“我们想做到多少”开始。
而应该从:
“用户到底能接受多少?”
开始。
可以问业务三个问题。
第一个问题:失败一次,会不会直接损失钱?
比如:
支付
资金结算
订单创建
库存扣减
这些通常优先级高。
第二个问题:用户能不能重试?
比如:
推荐
搜索
消息通知
数据刷新
用户重新点一次可能就好了。
这种场景通常不需要疯狂追求五个9。
第三个问题:故障有没有替代路径?
比如:
在线支付失败
↓
还能货到付款
短信失败
↓
还能 App 推送
推荐挂了
↓
还能商品搜索
有兜底,就意味着用户真实感知到的风险下降。
这时候 SLO 就可以相对宽松。
九、我更推荐“分层SLO”,而不是“一刀切”
实际生产环境可以建立这样一个模型:
产品
│
┌────────┼────────┐
│ │ │
核心 重要 辅助
│ │ │
99.99% 99.9% 99%
│ │ │
支付/订单 搜索 推荐
甚至可以进一步加入延迟。
例如:
services:
payment:
availability: 99.99%
latency_p99: 1000ms
order:
availability: 99.99%
latency_p99: 800ms
search:
availability: 99.95%
latency_p99: 500ms
recommendation:
availability: 99.0%
latency_p99: 2000ms
这样一来:
SLO终于和业务发生关系了。
十、还有一个特别容易忽略的问题:SLO一定要定义“测量边界”
比如订单服务:
用户
↓
CDN
↓
Gateway
↓
Nginx
↓
Order API
↓
Redis
↓
MySQL
↓
MQ
到底谁负责 SLO?
这是非常现实的问题。
如果你定义:
Order API 99.99%
但 MySQL 挂了导致订单全部失败。
API 层可能认为:
请求正常进入了
业务却认为:
订单根本没创建
所以真正有价值的 SLO,应该尽量贴近:
用户能不能完成业务目标。
例如:
订单创建成功率
比:
Order API HTTP 200比例
更接近业务。
十一、别忘了“业务SLO”和“技术SLO”不是一回事
这个区别特别重要。
例如:
技术指标:
API Availability >= 99.95%
MySQL Availability >= 99.99%
Redis Availability >= 99.99%
Kafka Availability >= 99.99%
看起来每个组件都很优秀。
但是业务指标:
订单成功率 = 99.5%
那还是有问题。
为什么?
因为复杂系统不是简单的:
99.99% + 99.99% + 99.99%
最后就等于 99.99%。
系统存在大量:
- 调用链
- 超时
- 重试
- 数据一致性
- 消息堆积
- 限流
- 降级
- 第三方依赖
所以真正应该盯住的,是:
最终业务结果。
十二、第三方依赖,也要纳入SLO设计
比如你的支付系统依赖第三方支付平台。
你自己的 SLO:
99.99%
但第三方:
99.9%
那你再怎么努力,也不可能轻松保证整个支付链路 99.99%。
所以这时候应该:
自己的服务 SLO
+
第三方依赖 SLO
+
降级能力
=
最终业务 SLO
比如:
支付服务
│
├── 支付宝
│
├── 微信支付
│
└── 银行通道
如果某一个通道挂掉:
自动切换其他通道
那么最终用户体验可能仍然保持稳定。
这时候真正值钱的就不是:
“我们单个支付接口99.999%。”
而是:
“任何一个支付通道出问题,用户依然可以完成支付。”
这才叫架构能力。
十三、SLO不要一年定一次,要动态调整
我特别反对一种做法:
年初定一次 SLO,然后年底复盘一下。
这其实没有多大意义。
因为业务会变化。
比如:
刚上线:
99%
用户增长:
99.9%
成为核心业务:
99.95%
交易规模扩大:
99.99%
SLO应该随着:
- 用户规模
- 业务重要性
- 收入贡献
- 用户投诉
- 技术成熟度
- 基础设施成本
不断调整。
甚至可以做成自动报表:
服务 SLO 当前值 预算消耗
------------------------------------------------
支付 99.99% 99.995% 20%
订单 99.99% 99.97% 65%
搜索 99.95% 99.98% 30%
推荐 99.00% 99.95% 10%
一眼就知道:
哪个系统真的危险。
十四、最后聊聊我对SLO最大的一个误解
以前我也觉得:
运维做好 SLO,就是把系统做到足够稳定。
后来才发现不是。
SLO真正解决的是“我们到底应该把时间和钱花在哪里”。
如果所有服务都要求:
99.99%
那最后的结果很可能是:
开发不敢上线
运维不敢变更
架构越来越复杂
成本越来越高
业务越来越慢
这其实也是一种失败。
真正成熟的团队应该敢于接受:
某些东西就是可以偶尔失败的。
推荐挂几分钟,也许没关系。
短信晚几秒,也许没关系。
后台报表慢一点,也许没关系。
但支付不能挂。
订单不能莫名其妙丢失。
用户已经付款,却不能查到订单,更不能接受。
所以我认为,一个好的 SLO 设计最终应该回答一句非常朴素的话:
“我们愿意为了什么体验,付出多少钱?”
如果这个问题回答清楚了,SLO 基本就不会离谱。
写在最后
SLO从来不是:
99.9%
99.99%
99.999%
这几个数字的游戏。
它背后其实是一个非常现实的工程问题:
用户需要什么?业务最怕什么?系统哪里最值得投入?
所以复杂产品设计 SLO,我建议按照这条路线走:
用户旅程
↓
核心业务
↓
SLI设计
↓
SLO分层
↓
Error Budget
↓
技术指标
↓
监控告警
↓
发布策略
↓
持续复盘
最后送给运维同行一句我自己比较认同的话:
不要为了把系统做到99.999%,把整个团队搞成99.999%的痛苦。
真正优秀的 SRE,不是让所有系统都永远不出问题。
而是知道:
什么问题绝对不能出,什么问题出了可以接受,以及为了减少那一次故障,到底值不值得再投入一倍成本。
这,才是 SLO 真正的价值。
- 点赞
- 收藏
- 关注作者
评论(0)