一、可用性怎么定义:两种口径
「可用性」不是一个自然存在的数字,而是你自己定义出来的。定义方式不同,同一个系统能算出完全不同的可用率。这是所有讨论的前提。
1.1 时间维度(传统运维口径)
Availability = 正常运行时间 正常运行时间 + 不可用时间 \text{Availability} = \frac{\text{正常运行时间}}{\text{正常运行时间} + \text{不可用时间}} Availability=正常运行时间+不可用时间正常运行时间
问题在于「不可用」的判定极其模糊:部分接口 500 算不算?响应从 50ms 涨到 5s 算不算?10% 的用户受影响算不算?这个口径在分布式系统里几乎无法客观执行,因为现代故障大多是「部分降级」而非「整体宕机」。
1.2 请求维度(SRE 口径,推荐)
Availability = 成功请求数 总请求数 \text{Availability} = \frac{\text{成功请求数}}{\text{总请求数}} Availability=总请求数成功请求数
这个口径可客观测量、可自动计算、天然反映用户实际感知。Google SRE 和主流云厂商都用它。
但**「成功」的定义必须写清楚**,否则数字没有意义。一个完整的定义应该长这样:
在 5 分钟滚动窗口内,
/api/order/create的 HTTP 状态码非 5xx 且 P99 延迟 < 500ms 的请求占比。
注意两点:
- 必须包含延迟条件 。只统计错误率的话,一个「所有请求都返回 200 但耗时 30 秒」的系统可用性是 100%------而用户早就跑了。慢等于不可用。
- 4xx 通常不计入(客户端自己参数传错,不是你的故障),但要小心 401/429 这类可能由服务端问题引发的状态码。
二、MTBF 与 MTTR:可用性的两个杠杆
从可靠性工程的角度,可用性还有一个等价表达:
Availability = MTBF MTBF + MTTR \text{Availability} = \frac{\text{MTBF}}{\text{MTBF} + \text{MTTR}} Availability=MTBF+MTTRMTBF
这个公式揭示了一个关键判断:追求「不出故障」是徒劳的,工程重心应该放在「快速恢复」上。
原因是 MTBF 的提升有物理上限(硬件会坏、网络会抖、依赖方会挂、人会误操作),而 MTTR 的压缩空间巨大。把 MTTR 从 30 分钟压到 3 分钟,可用性直接提升一个数量级,成本远低于把 MTBF 翻十倍。
MTTR 还能继续拆解,这是排查优化点的正确方式:
MTTR = 发现 ⏟ MTTD + 定位 + 修复 + 验证 \text{MTTR} = \underbrace{\text{发现}}_{\text{MTTD}} + \text{定位} + \text{修复} + \text{验证} MTTR=MTTD 发现+定位+修复+验证
| 阶段 | 优化手段 |
|---|---|
| 发现(MTTD) | 监控告警覆盖率。很多故障是用户投诉才发现的,这个阶段往往占 MTTR 的大头 |
| 定位 | 链路追踪、结构化日志、指标下钻 |
| 修复 | 一键回滚、开关降级、快速扩容------预案要提前演练,不是故障时现写脚本 |
| 验证 | 自动化冒烟验证 |
你做 Monitor 项目,本质上就是在攻 MTTD 这一段------它是整条链路上性价比最高的投入点。
三、几个 9 分别意味着什么
以下数字为实际计算结果(年按 365 天,月按 30 天):
| 可用性 | 年停机 | 月停机 | 周停机 | 日停机 | 典型定位 |
|---|---|---|---|---|---|
| 99%(2 个 9) | 3.65 天 | 7.2 小时 | 1.68 小时 | 14.4 分钟 | 内部工具、离线任务 |
| 99.9%(3 个 9) | 8.76 小时 | 43.2 分钟 | 10.08 分钟 | 1.44 分钟 | 一般业务系统,多数 SLA 的起点 |
| 99.95% | 4.38 小时 | 21.6 分钟 | 5.04 分钟 | 43.2 秒 | 云厂商常见承诺档 |
| 99.99%(4 个 9) | 52.56 分钟 | 4.32 分钟 | 1.01 分钟 | 8.64 秒 | 核心交易、支付链路 |
| 99.999%(5 个 9) | 5.26 分钟 | 25.92 秒 | 6.05 秒 | 0.86 秒 | 电信级、金融清算 |
| 99.9999%(6 个 9) | 31.54 秒 | 2.59 秒 | 0.6 秒 | 0.09 秒 | 极少数系统真正需要 |
每多一个 9,容错时间就除以 10,而成本远不止乘以 10。 几个关键的现实约束:
- 99.99% 意味着全年只有 52 分钟。 一次「发现 + 拉群 + 定位 + 回滚 + 验证」的常规故障处理就是 20~30 分钟。也就是说,全年只能出两次故障,而且必须处理得很快。
- 99.999% 意味着全年 5 分钟。 人工介入在这个量级下根本来不及------从收到告警到人打开电脑就超预算了。必须全自动故障转移、自动熔断、自动切流,人只能事后复盘。
- 发布本身就在消耗预算。 一次滚动发布如果有 30 秒的连接抖动,一个月发 10 次,就是 5 分钟------已经超过 99.99% 的月度预算(4.32 分钟)。所以高可用系统必须做到发布无损(优雅摘流量、连接优雅关闭)。
四、最容易被忽略的事:串联的乘法效应
这是微服务架构下最重要的可用性认知:
串联的衰减比直觉严重得多。以下是每个环节都做到 99.9% 时,整体可用性随依赖数量的变化:
| 强依赖数量 | 整体可用性 | 年停机 |
|---|---|---|
| 1 个 | 99.900% | 8.76 小时 |
| 3 个 | 99.700% | 1.09 天 |
| 5 个 | 99.501% | 1.82 天 |
| 10 个 | 99.005% | 3.63 天 |
| 20 个 | 98.019% | 7.23 天 |
| 50 个 | 95.121% | 17.81 天 |
结论很残酷 :一条请求链路上如果有 10 个强依赖(网关 + 鉴权 + 订单 + 库存 + 风控 + 优惠 + 支付 + MySQL + Redis + MQ),每个都做到 99.9%,整体只有 99%------连 3 个 9 都达不到。而要让整体达到 99.99%,每个环节需要做到 99.999%,这在工程上不现实。
所以提升整体可用性的正确路径不是「让每个服务更可靠」,而是减少强依赖的数量:
| 依赖类型 | 定义 | 处理策略 |
|---|---|---|
| 强依赖 | 挂了请求必然失败(订单 → MySQL) | 必须冗余、必须高可用 |
| 弱依赖 | 挂了可以降级(订单 → 推荐服务) | 熔断 + 降级,从可用性公式中剔除 |
一次认真的「强弱依赖梳理」评审,对可用性的提升往往超过堆一倍机器。
4.1 并联冗余有个前提:故障必须独立
1 − ( 1 − A ) n 1 - (1-A)^n 1−(1−A)n 这个公式成立的前提是各副本故障相互独立。现实中往往不独立:
| 相关故障来源 | 后果 |
|---|---|
| 同一机房 | 断电/断网,所有副本一起挂 |
| 同一份代码 | 一个 NPE bug,所有副本同时崩 |
| 同一配置中心 | 一次错误的配置推送,全军覆没 |
| 同一下游依赖 | 都连同一个 DB,DB 挂了全挂 |
所以数学计算出的可用性是理论上限 。真实世界里,绝大多数重大故障都是相关故障(correlated failure) ------这也正是多可用区、多地域部署的意义:它买的是「故障域隔离」,而不是单纯的副本数量。
同理,「同一份代码的 100 个副本」在代码 bug 面前的可用性等于 1 个副本。这就是灰度发布存在的理由。
五、SLI / SLO / SLA 与错误预算
这三个词经常被混用,但含义完全不同:
| 概念 | 全称 | 含义 | 例子 |
|---|---|---|---|
| SLI | Indicator | 实际测量的指标 | 上月非 5xx 且 P99<500ms 的请求占比 = 99.97% |
| SLO | Objective | 内部目标 | 目标 ≥ 99.95% |
| SLA | Agreement | 对外合同承诺,违约要赔钱 | 承诺 99.9%,未达标赔偿 10% 服务费 |
关键实践:SLA 必须明显低于 SLO。对外承诺 99.9%,内部目标定 99.95%,这中间的差额就是你的安全垫。如果 SLA 和 SLO 相等,那意味着任何一次波动都会直接触发赔偿。
5.1 错误预算(Error Budget)------ 最实用的管理工具
Error Budget = 1 − SLO \text{Error Budget} = 1 - \text{SLO} Error Budget=1−SLO
SLO 定 99.9%,则每月的错误预算是 43.2 分钟。这个数字的用法是:
| 预算状态 | 行动 |
|---|---|
| 预算充足 | 可以快速上线新功能、可以做混沌工程演练、可以承担一定风险 |
| 预算耗尽 | 冻结功能发布,全员转向稳定性工作,直到下个周期预算重置 |
这个机制的真正价值在于------它把「稳定性」和「迭代速度」这个永恒的矛盾变成了一个可量化、可仲裁的数字。业务方要求快速上线、SRE 要求稳定,双方不需要吵架,看预算余额就行。预算没了,规则说停就停;预算还有,就放手迭代。
它同时也暗示了一个反直觉的观点:可用性不该无限追求。 如果一个季度下来错误预算完全没用掉,说明你在稳定性上过度投入了,那些资源本可以用于业务创新。
六、工程实践建议
6.1 不要盲目追求高 9,先算业务账
定 SLO 的正确方式是回答两个问题:
- 停机一分钟的业务损失是多少?(营收损失 + 品牌损失 + 赔偿)
- 多加一个 9 的工程成本是多少?(多机房、冗余资源、自动化建设、人力投入)
当边际成本超过边际收益时就该停。绝大多数业务系统的合理答案是 99.9% ~ 99.99%,而不是 5 个 9。
6.2 分级定义,不要全站一个标准
| 分级 | 系统 | SLO |
|---|---|---|
| P0 核心 | 下单、支付、登录 | 99.99% |
| P1 重要 | 商品详情、购物车 | 99.95% |
| P2 一般 | 评论、推荐、营销页 | 99.9% |
| P3 内部 | 后台管理、报表 | 99% |
6.3 其他要点
- 按用户感知定义 SLI,不要用服务器指标。CPU 100% 但请求都成功,那就是可用的;CPU 10% 但全部超时,那就是不可用的。
- 发布必须无损:优雅摘流量 → 等存量请求处理完 → 停机。你之前研究的连接池 TTL 与服务端 keepalive 配合,就是无损发布的一环。
- 预案要演练。没演练过的预案在故障时等于不存在------故障现场没人有心情读文档。
- 定期混沌演练,主动注入故障验证冗余是否真的生效。很多「双活」架构在真正断网时才发现从来没切换成功过。
小结
| 问题 | 答案 |
|---|---|
| 可用性怎么定义 | 推荐请求维度:成功请求数 / 总请求数,且必须包含延迟条件(慢等于不可用) |
| 另一个等价公式 | 可用性 = MTBF /(MTBF + MTTR) |
| 该往哪投入 | 压缩 MTTR,尤其是 MTTD(发现时间),性价比远高于追求零故障 |
| 99.9% 意味着 | 年停 8.76 小时,月停 43.2 分钟 |
| 99.99% 意味着 | 年停仅 52.56 分钟,全年只允许出两次故障,发布必须无损 |
| 99.999% 意味着 | 年停 5.26 分钟,人工介入来不及,必须全自动故障转移 |
| 最容易被忽略的 | 串联乘法效应------10 个 99.9% 的强依赖串起来只有 99% |
| 提升可用性的正确路径 | 减少强依赖数量(弱依赖化 + 熔断降级)> 让每个服务更可靠 |
| 冗余的隐含前提 | 故障相互独立。相关故障(同机房/同代码/同配置)是数学公式失效的主因 |
| 最实用的管理工具 | 错误预算:预算充足则放手迭代,耗尽则冻结发布 |
一句话总结:可用性不是技术指标,而是一个商业决策。定 SLO 的过程本质是在回答「为了少停机一分钟,你愿意花多少钱」,而不是「技术上能做到几个 9」。