Appearance
高可用和容灾
高可用和容灾经常被一起提到,但其实是两个层次的东西。高可用处理的是局部故障后的继续服务能力——单台机器挂了、某个 Pod 崩了、某条网络断了,系统能不能继续跑;容灾处理的是更大范围故障后的恢复能力——整个机房不可用、某个城市断网断电、某个云区域整体挂了,系统还能不能从异地拉起来。
打个比方,高可用就像家里备着手电筒和备用钥匙,平时应急用;容灾就像在外地还有一套备用的房子和生活物资,真的大灾难来了能搬过去住。两者都会碰到备份、切换、数据同步、定期演练这些事,只是影响范围完全不同——单机坏了能切到备机是高可用,整个机房不可用后还能从异地恢复才是容灾。
一、RTO 和 RPO
容灾方案设计里,有两个人们最爱拿出来讨论的指标:
| 指标 | 含义 |
|---|---|
| RTO(Recovery Time Objective) | 故障发生之后,业务恢复需要多久 |
| RPO(Recovery Point Objective) | 故障发生之后,最多能丢多长时间的数据 |
举个具体例子感受一下:如果系统每天凌晨 0 点做一次全量备份,上午 10 点数据库损坏,只能恢复到 0 点那份备份——那么从 0 点到 10 点这 10 个小时的写入全部丢失,RPO 接近 10 小时。如果从准备机器、恢复备份到业务重新可用一共花了 2 小时,RTO 就是 2 小时。
RTO 和 RPO 越小,成本越高——这是铁律。分钟级恢复和小时级恢复,完全是两套投入;不丢数据和允许丢几分钟数据,完全是两种架构。所以设计容灾方案时,先跟业务方对齐:这个系统能容忍多久不可用?能容忍丢多少数据?根据答案反推架构,而不是无脑追求"零 RPO 零 RTO"——那种方案成本高到绝大多数业务都承受不起。
二、备份恢复
备份是容灾的底线,这个没什么好商量的。误删、勒索病毒、存储损坏、运维误操作,任何一件都能把线上数据毁掉,只有备份能救。
但备份不只是"做了就行",要看这几个关键点:
| 事项 | 要确认什么 |
|---|---|
| 频率 | 每小时、每天,还是按业务事件备份——决定 RPO 上限 |
| 保留周期 | 保留几天、几周、几个月——决定能恢复到多久之前 |
| 异地保存 | 备份不能跟源数据放一起,不然机房挂了备份也没了 |
| 权限隔离 | 误删生产的人不能顺手把备份也删了——权限要分开 |
| 恢复演练 | 备份文件能不能真的在目标环境恢复出来 |
最后这一条是最容易被忽略的。备份文件存在 ≠ 能恢复成功。压缩包损坏、账号权限不够、数据库版本不兼容、缺少 binlog 导致无法做基于时间点的恢复、对象存储跨区域同步没完成……这些坑都能让"以为有备份"在真出事的时候变成"备份用不了"。
所以定期要做完整的恢复演练——找一套目标环境,把备份真正恢复进去,应用连上去跑关键业务查询,验证数据完整性。这样才知道备份到底能不能用、恢复大概需要多久。光看"备份任务执行成功"的日志完全不够。
三、主备和异地备
主备一般处理的是单组件或者单机房内的故障,响应快。异地备把数据或者服务放到另一个地理位置,用来应对更大范围的故障(机房整体不可用、城市级灾难)。
| 形态 | 特点 |
|---|---|
| 本地主备 | 切换快,适合单机或单组件故障 |
| 异地备份 | 成本低,但恢复时间长(要从异地拉数据重建) |
| 异地冷备 | 平时不跑完整业务,故障时才拉起,成本中等 |
| 异地热备 | 备站持续同步数据并保持就绪,切换最快但成本最高 |
异地备的核心是两件事:数据怎么过去、入口怎么切过去。数据同步慢,RPO 就大;入口切换慢,RTO 就长。这两个指标直接由异地备的实现方式决定。
举个真实场景:数据库异步复制到异地,主站故障的时候,异地还差 3 分钟的 binlog 没追上。业务恢复到异地之后,这 3 分钟内的写入就要靠业务侧的补偿、对账、甚至人工处理来弥补——这就是 RPO 的实际代价。如果业务对这 3 分钟数据非常敏感,那就要考虑同步复制或者半同步复制,但延迟和性能成本会更高。
四、同城双活
同城双活指同一个城市内两个机房同时承载业务。两个机房距离近(同城几十公里以内),网络延迟低(通常 1-2ms),适合做流量分担和实时数据同步。
同城双活主要解决的是:单机房故障、机房内网络设备故障、局部供电故障。两边平时都接流量,故障时一边直接接管,不需要从零拉起备站,切换速度很快。
难点还是在数据上。读多写少的系统比较容易做双活——两边都能查,写入集中在某一个机房就行;强一致写入的双活系统就要看"写入归属"怎么设计——两边同时写同一份数据,就必然碰到冲突处理,工程上非常复杂。所以真正做"写双活"的系统不多,大部分双活还是"读双活+单点写"。
五、异地双活
异地双活把不同城市或者不同区域同时作为业务入口。它能抵御城市级或者区域级故障——某个城市整体不可用,业务还能在另一个城市继续跑。但跨地域延迟(几十到一百多毫秒)、数据一致性、运维复杂度都会大幅上升。
实际工程里,真正"任意请求打到任意城市"的异地双活极少。更常见的是按用户、地域、业务单元分流:
| 分流方式 | 怎么做 |
|---|---|
| 按地域 | 华东用户主要访问华东机房、华北用户主要访问华北机房 |
| 按用户 | 用户归属固定到某个区域,写入不跨区乱跑 |
| 按业务 | 查询多地可用,核心写入固定在某个主区域 |
这种"单元化"思路能最大限度减少跨地域写冲突。代价是用户归属如果需要变化(用户搬家、业务迁移),登录态、缓存、订单状态、消息消费位移都会跟着复杂——切换归属这件事本身就不简单。
六、两地三中心
两地三中心是国内传统企业(尤其金融、电信、政务)最常见的容灾形态:同城两个中心 + 异地一个灾备中心。
| 中心 | 干什么 |
|---|---|
| 同城生产中心 | 承载主要业务流量 |
| 同城灾备中心 | 低延迟接管,处理本地中心故障 |
| 异地灾备中心 | 处理城市级灾难 |
同城两个中心之间距离近,可以做同步或者准同步复制(数据几乎不丢);异地中心距离远,一般做异步复制(可能丢少量数据)。这样组合下来,既有本地快速切换的能力(应对机房级故障),也有城市级灾难后的恢复位置(应对极端情况)。
这里要分清一件事:"有机房"和"可切换"是两回事。异地中心如果只是租了机房、装了机器,但没有持续同步数据、没有定义入口切换流程、没有定期演练——那只能算"有资源",不能算"可靠容灾"。真出事的时候,根本切不过去。所以容灾不是买个异地机房就完了,而是要持续投入运营,定期演练。
七、多活风险
多活听起来很美好,但实际落地会牵动系统的方方面面,每一处都可能成为新的故障源:
| 风险 | 实际表现 |
|---|---|
| 写冲突 | 两个机房同时修改同一条数据,合并时不知道以谁为准 |
| 缓存不一致 | 用户在不同机房看到不同的状态(头疼的体验问题) |
| 消息重复消费 | 两边都消费了同一个事件,导致业务被处理两次 |
| 定时任务重复执行 | 定时任务在多个机房同时跑,发两次邮件、扣两次款 |
| 切换不完整 | 入口已经切走,但后端、数据库、消息队列还在旧链路 |
容灾演练必须跑完整业务路径,不是只切一下网络入口就算完。登录、查询、下单、支付、文件上传、后台任务、报表导出——每一条主流程都要走一遍,看在切换后的新机房能不能正常工作。
演练记录里要写实际结果,比如"入口 14:20 切到异地,登录 14:22 恢复,订单查询 14:25 恢复,报表任务因队列消费者未启动失败"——这种记录能直接暴露哪些系统还没真正进入容灾链路。光记一句"演练成功"等于没演练,真出事的时候该踩的坑一个都少不了。