最近在系统设计评审里,跟系统可靠性相关的话听得特别多。有人问:服务都上了容器编排,多副本也做了,为什么线上还是经常出问题?也有人问:SLA写了三个九四个九,但故障恢复只停留在重启和回滚层面,是不是等于没有?这些问题绕来绕去,最后都会回到同一个点:可靠性到底是在分析阶段就要想清楚的事,还是上线以后靠运维去补救的事?我做系统设计和稳定性保障这些年,最大的体会是,这恰恰是所有环节里最不该往后放的一章。
今天这篇就不按教材顺序写了,只聊我认为最实操的路径:先把可靠性分析和指标定义做扎实,再看架构层面怎么设计容错,然后讲验证手段,最后聊团队和流程怎么把这些事长期运转起来。面向的读者是做架构、后端研发、SRE、技术负责人的同学。我会尽量把每个环节背后的“为什么”讲清楚,也会把我踩过的坑直接摆出来。可靠性设计这件事,不是把PPT写得漂亮就完了,而是靠一个又一个具体选择堆积出来的。
1. 可靠性分析:先把指标和风险摸清楚
1.1 可用性目标不是拍脑袋定“几个九”
很多团队一提可用性,第一反应就是“我们要做到99.99%”。但问起为什么是99.99%、当前离这个目标还差多少、达不成会有什么后果,基本没有统一答案。目标一旦拍脑袋,后面所有的保障动作也会跟着拍脑袋。
先看一组基础数字:99%的可用性意味着每年有大约3.65天不可用,99.9%是8.76小时,99.99%是52.6分钟,99.999%是5.26分钟。这里的“不可用时间”是全年累计值,包括凌晨、节假日、大促期间所有用户实际无法访问的时间。如果业务完全不允许在白天有故障窗口,那“4个9”对应的一年52分钟额度,分摊到12个月里其实非常紧张,一次核心链路故障就可能用掉一半预算。
这组数字不是用来写PPT的,它直接决定了架构投入和技术选型。我见过一个团队给内部运营后台定了99.99%的SLO,结果运营后台主要使用时间是工作日9点到19点,晚上和周末几乎没有访问,团队却为了这“4个9”投入大量精力做跨机房容灾,属于典型的预算错配。
可用性还可以拆成两个维度来理解:平均故障间隔时间MTBF和平均恢复时间MTTR。可用性约等于MTBF除以MTBF与MTTR之和。这个简化公式告诉我们一个很朴素的道理:故障不可能完全消除,但让故障恢复得更快,往往比单纯追求不发生故障更容易做到。代码写得再小心,物理机也会坏、依赖也会抖、网络也会闪断。所以可靠性工作的重心,在故障发生后如何快速恢复这件事上,投入产出比通常更高。
在实践中,目标口径不要只看一个全年数字。要跟业务方确认清楚:是否包含计划内维护窗口?是否只统计核心链路?是否允许在低峰时段有短时间不可用?把这些边界定清楚之后,每月再看剩余的错误预算。如果本月故障已经消耗了大部分不可用时间,剩余时间就不应该再做高风险的变更。这就是SLO和变更管理之间的联动。
1.2 FMEA:在故障发生前把风险点摆上桌
做可靠性分析,最怕凭印象说“这里应该没问题”。我自己用过最顺手的方法是FMEA,故障模式与影响分析。它不复杂,核心是把系统拆开,逐个环节追问“如果它出问题,会发生什么”,然后按风险大小排序,给出应对动作。
具体操作上,我建议按四步走。第一步,画出核心业务链路,从用户入口到所有依赖项,包括服务、数据库、缓存、消息队列、第三方接口、对象存储等,全部列出来。第二步,针对每个环节问三句话:它挂了会怎样?它变慢了会怎样?它返回错误数据会怎样?第三步,给每个故障模式从三个维度打分:严重度S,业务影响有多大;发生频度O,发生的可能性有多高;可检测度D,故障发生后我们能不能及时发现。需要说明的是,这里D的评分方向通常是反向的:D分越高代表越难发现,D分越低代表监控能立刻感知。第四步,用严重度乘以发生频度再乘以可检测度,得到RPN风险系数,按数值从高到低排序,逐项落实缓解动作。
举个例子,一个订单系统在FMEA分析时,可以列出这样的故障模式:
| 链路环节 | 故障模式 | 严重度S | 发生频度O | 可检测度D | RPN |
|---|---|---|---|---|---|
| 应用实例 | 容器OOM导致服务重启 | 5 | 6 | 4 | 120 |
| 主数据库 | 磁盘写满 | 10 | 2 | 2 | 40 |
| 支付平台 | 异步回调延迟 | 8 | 4 | 7 | 224 |
| 下游库存 | 接口变慢拖垮线程池 | 9 | 4 | 6 | 216 |
| 缓存集群 | 大量key同时失效 | 6 | 5 | 3 |
