Skip to content

高可用和容灾

高可用和容灾经常被一起提到,但其实是两个层次的东西。高可用处理的是局部故障后的继续服务能力——单台机器挂了、某个 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 恢复,报表任务因队列消费者未启动失败"——这种记录能直接暴露哪些系统还没真正进入容灾链路。光记一句"演练成功"等于没演练,真出事的时候该踩的坑一个都少不了。