Skip to content

第 15 讲|高可用和容灾

高可用(High Availability)容灾(Disaster Recovery) 经常被一起提到,但解决的是不同层次的问题

维度高可用容灾
故障范围局部:单机、单组件、单服务大范围:机房、城市、区域
应对手段主备、集群、健康检查、自动切换异地备份、跨地域同步、灾备站点
切换时间秒级到分钟级分钟级到小时级
数据完整性通常零丢失可能丢失少量数据
成本中等高(尤其多活)

简言之:高可用应对"小故障",容灾应对"大灾难"。两者都涉及备份、切换、同步、演练,但影响范围和投入完全不同。

本讲围绕容灾的核心展开:RTO/RPO 指标、备份恢复的工程要求、主备与异地备的差异、同城双活、异地双活、两地三中心、多活架构的风险。

一、RTO 和 RPO:容灾的两个核心指标

容灾方案设计的两个最重要指标:

RTO 和 RPO 分别衡量恢复时间和数据丢失窗口

指标含义衡量什么
RTO(Recovery Time Objective)故障后业务恢复需要多久服务停摆时间
RPO(Recovery Point Objective)故障后最多丢失多长时间的数据数据丢失量

一个具体例子

某系统每天凌晨 0 点做一次全量备份,上午 10 点数据库损坏:

  • 只能恢复到 0 点那份备份 → 0:00 到 10:00 的写入全部丢失,RPO ≈ 10 小时
  • 从准备机器、恢复备份到业务可用花了 2 小时 → RTO = 2 小时

RTO 和 RPO 与成本的关系

RTO 和 RPO 越小,成本越高——这是容灾设计的铁律。

RTO / RPO方案相对成本
RTO 数小时 / RPO 一天每日备份 + 故障时手工恢复
RTO 数分钟 / RPO 数分钟主备 + binlog 持续归档5-10×
RTO 秒级 / RPO 接近零同城双活 + 同步复制30-50×
RTO 秒级 / RPO 零异地多活 + 强一致100×+

容灾方案设计的第一步是与业务方对齐目标:

  • 这个系统能容忍多久不可用?
  • 能容忍丢失多少数据?

根据业务实际承受能力反推架构,而不是盲目追求"零 RPO 零 RTO"。绝大多数业务并不需要那种级别的保障——把所有成本都堆到容灾上,反而拖垮整个系统经济性。

不同业务的合理目标

业务类型典型 RTO典型 RPO
内部低频工具数小时到一天一天
一般 SaaS 业务数十分钟数分钟到一小时
电商业务(非交易)分钟级秒级
在线交易、支付秒级接近零
金融核心秒级零(异步丢失也不可接受)

二、备份恢复:容灾的底线

备份是容灾的绝对底线——所有更高级的容灾形态(主备、双活、多活)都建立在备份之上。

备份必须经过恢复演练才算可靠

备份能应对的故障

主备/复制能应对的故障(节点故障、机房故障),备份能应对所有故障,包括:

  • 误删数据(DROP TABLEDELETE 无 WHERE)
  • 应用 bug 写脏数据
  • 勒索病毒加密数据
  • 存储损坏
  • 主从复制把误操作同步走了
  • 配置错误导致数据被覆盖
  • 安全事件后数据篡改

这些场景下复制完全无效(因为错误操作会被同步到所有副本),只有从历史时间点的备份才能恢复。

备份不是"做了就行"

要保证备份真正可用,需要确认:

维度要确认什么
频率每小时/每天?决定 RPO 上限
保留周期保留几天/几周/几个月?决定能恢复到多久之前
异地保存备份必须跟源数据物理隔离
权限隔离误删生产的人不能顺手删备份
加密备份本身要加密,防止泄露
校验定期验证备份文件完整性
恢复演练备份能不能真的恢复出来

"备份未演练 = 没有备份"

最容易被忽略的是恢复演练。备份文件存在 ≠ 能恢复成功。常见失效情况:

失效原因现场表现
压缩包损坏解压报错
账号权限不够恢复时无法写入目标位置
数据库版本不兼容备份是 MySQL 5.7,目标是 8.0
缺少 binlog全量备份能恢复但无法基于时间点恢复
对象存储跨区域同步未完成异地备份其实还没到位
加密 key 丢失备份文件无法解密
备份文件其实是空的备份脚本失败但没人发现

这些情况都让"以为有备份"变成"备份用不了"——真正发现问题时,损失已经无法挽回。

恢复演练的标准流程

第 1 步:准备一套与生产隔离的目标环境
第 2 步:从备份系统拉取最新备份文件
第 3 步:在目标环境完整恢复(数据库 + 配置 + 文件)
第 4 步:启动应用连接恢复的数据库
第 5 步:跑关键业务查询,验证数据完整性
第 6 步:对比生产数据,确认恢复点正确
第 7 步:记录恢复耗时、问题、改进点

只看"备份任务执行成功"日志远远不够——必须真正恢复出来才算备份有效。建议频率:

  • 关键业务系统:每月一次
  • 一般业务系统:每季度一次
  • 边缘系统:每半年一次

备份的 3-2-1 原则

业界经典的备份原则:

  • 3 份数据副本(生产 + 2 份备份)
  • 2 种不同存储介质(磁盘 + 对象存储)
  • 1 份异地存储

这个原则同时防御了硬件故障、单点存储故障、机房级灾难三类问题。

三、主备与异地备

异地异步复制天然有 RPO 数据窗口

各种备份形态的对比

形态数据同步方式RTORPO成本
本地主备同步/半同步复制秒级接近零
异地备份定期备份传输到异地数小时备份间隔
异地冷备异步复制 + 平时不运行业务数十分钟到小时复制延迟
异地热备实时同步 + 持续就绪分钟级接近零
同城双活同步复制 + 两边都运行秒级
异地双活异步复制 + 两边都运行秒级秒级极高

异地备的两个核心问题

数据怎么过去入口怎么切过去——这两个问题决定异地备的实际效果。

问题影响
数据同步慢RPO 大,可能丢失大量数据
入口切换慢RTO 长,业务停摆时间长
数据同步延迟监控不监控就不知道实际 RPO
入口切换流程未演练真出事时切不过去

异地异步复制的 RPO 代价

场景:数据库异步复制到异地机房
14:00:00 主站故障,业务转移到异地
14:00:00 异地数据落后主站 3 分钟
14:00:00 主站 13:57-14:00 的写入,异地没有

后果:
- 这 3 分钟的订单可能丢失
- 用户已经收到的"创建成功"反馈,异地查不到对应订单
- 需要业务侧的补偿、对账、人工处理

RPO 不是数字游戏,是实实在在的业务损失——3 分钟数据丢失对支付系统可能意味着数百笔交易要人工对账。

业务对数据敏感时,要用更严格的同步方式:

  • 半同步复制 — 主库等至少一个从库确认才提交
  • 同步复制 — 主库等所有副本都确认
  • 强一致协议(Raft/Paxos)— 多数派确认

代价是写入延迟和性能下降——选择哪种取决于业务对一致性的真实需求。

四、同城双活

同城双活:同一城市的两个机房同时承载业务

同城双活的特点

维度说明
距离同城内通常几十公里
网络延迟1-3ms
同步方式可以做同步或半同步复制
故障覆盖单机房故障、机房网络设备故障、局部停电
切换时间秒级到分钟级
数据丢失接近零

同城双活解决什么问题

  • 单机房硬件故障
  • 机房网络中断
  • 机房供电故障
  • 机房空调失效
  • 单机房整体维护

两边平时都接流量,故障时一边接管全部流量,不需要从冷启动拉起——切换时间远短于异地备。

同城双活的难点:数据双活

读多写少的系统比较容易做双活——两边都能查询,写入集中在某一机房就够了。

强一致写入的双活就要看"写入归属"怎么设计——两边同时写同一份数据必然碰到冲突:

写入策略含义难点
单写双读写只在一个机房,两边都能读写入机房故障时仍需切换
双写 + 同步复制两边都能写,通过同步复制保证一致跨机房同步延迟,性能下降
双写 + 分片数据分片,每片有归属机房工程复杂,跨片操作受限
双写 + 冲突解决通过 CRDT、最后写入获胜等机制业务侧要适应

实际生产中真正做"全部双写"的系统很少,大部分双活是 "读双活 + 单点写"——两边都接读流量,写流量通过路由集中到某一边。

五、异地双活

异地双活:不同城市或不同区域同时承载业务。

异地双活解决什么问题

  • 城市级灾难(地震、洪水、大规模停电)
  • 区域级故障(运营商网络故障覆盖整个城市)
  • 国家级监管要求(某些行业要求数据不能跨境)
  • 用户就近接入(全球业务,降低延迟)

异地双活的难点

异地双活的难度远高于同城双活:

难点表现
跨地域延迟几十毫秒到 100ms+,同步操作变得困难
数据一致性强同步性能不可接受,只能异步 + 业务补偿
网络成本跨区域专线昂贵
运维复杂度双倍的环境,部署、监控、变更都要协调
切换协调多个组件同时切换的协调难度极大

单元化:异地双活的现实方案

真正"任意请求打到任意区域"的异地双活极少。更常见的是按某种维度分流(单元化):

分流维度工作方式
按地域华东用户主要访问华东机房,华北用户主要访问华北机房
按用户 ID 哈希用户固定归属某一区域,数据写入归属区域
按业务单元不同业务在不同区域,业务间通过 API 互相调用
按时间不同时段流量切到不同区域(主要用于切流演练)

单元化的核心思想:让每个用户的写入都在自己归属的单元完成,避免跨单元写冲突。

用户归属切换的复杂度

单元化的代价是用户归属一旦需要变化(用户搬家、业务迁移、灾备切换),涉及的状态同步极其复杂:

  • 登录态 — 跨单元 session 不通,需要重新登录
  • 缓存 — 用户相关的缓存在哪个单元?
  • 订单状态 — 进行中的订单怎么迁移?
  • 消息消费位移 — Kafka consumer offset 是单元独立的
  • 第三方依赖 — 支付、短信等回调地址需要切换

单元归属切换本身就是个复杂工程,不是 DNS 切一下就完事的。

六、两地三中心

两地三中心是国内传统企业(尤其金融、电信、政务)最常见的容灾形态:

两地三中心要区分有机房和可切换

  • 同城两个生产中心
  • 异地一个灾备中心

各中心的角色

中心职责
同城生产中心承载主要业务流量
同城灾备中心低延迟接管,处理本地中心故障
异地灾备中心处理城市级灾难

各中心的同步策略

  • 同城两中心:距离近,可以做同步或半同步复制(数据几乎不丢)
  • 异地中心:距离远,一般做异步复制(可能丢少量数据)

这样组合下来:

  • 本地快速切换(应对机房级故障)
  • 异地兜底(应对城市级灾难)

"有机房"和"可切换"是两回事

异地灾备最大的认知陷阱:

  • 异地机房租了 ✓
  • 异地机器装了 ✓
  • 异地数据同步了 ✓
  • 异地业务从没真正切过 ✗

这种状态下,异地中心只是"有资源",不是"可靠容灾"——真出事时,可能切不过去,或切过去后业务跑不通。

完整的可靠容灾要持续投入:

持续工作频率
数据同步监控实时
配置同步每次变更
应用部署同步每次发布
完整切换演练每年至少 1 次
部分切换演练每季度
灾备站点扩容跟生产一起
灾备人员培训每年

异地灾备的运营成本可能比一个普通业务集群还高——但这是真正能用的容灾必须付的代价。

七、多活架构的风险

多活听起来美好(故障无感、性能更好、容灾天然),但实际落地涉及系统的方方面面,每一处都可能成为新故障源。

主要风险点

风险表现
写冲突两个机房同时修改同一数据,合并时不知道以谁为准
缓存不一致用户在不同机房看到不同状态
消息重复消费两边都消费同一事件,业务被处理两次
定时任务重复定时任务在多机房同时跑,发两次邮件、扣两次款
切换不完整入口切走但后端、数据库、消息队列还在旧链路
Session 跨域用户在 A 机房登录,请求被路由到 B 机房,登录态失效
跨域调用延迟单元内调用 ms 级,跨单元调用几十毫秒
数据回流异地的数据要回流到主站做汇总分析

容灾演练:必须跑完整业务路径

容灾演练不是"切个 DNS 看能不能 ping 通"——必须跑完整业务路径:

  • 用户登录
  • 商品查询
  • 下单流程
  • 支付流程
  • 文件上传/下载
  • 后台任务
  • 报表导出
  • 第三方回调

每条主流程都要走一遍,验证切换后的新机房能正常工作。

演练记录要写实际结果

记录格式参考:

演练时间:2026-06-01 02:00
演练范围:全量切到异地灾备中心
实际结果:

02:00 - 触发切换
02:01 - 入口 DNS 切换完成
02:03 - 异地数据库提升为主
02:05 - 应用集群启动,健康检查通过
02:07 - 登录功能恢复 ✓
02:09 - 商品查询恢复 ✓
02:12 - 下单流程恢复 ✓
02:15 - 支付回调失败! 第三方支付的回调地址还指向原主站
02:18 - 手动修改支付回调配置
02:25 - 报表任务失败,异地的 Kafka consumer 没启动
02:30 - 启动 consumer,报表恢复
02:35 - 切回原主站

问题清单:
1. 支付回调地址未纳入切换流程
2. Kafka consumer 在异地需要手动启动
3. 应用启动后 5 分钟才完全 ready,需要优化健康检查

这种暴露问题的演练记录,远比"演练成功"四个字有价值——真正暴露问题、推动修复,才是演练的目的。

光说"演练成功"等于没演练,真出事时该踩的坑一个都少不了。

八、容灾的成本-收益评估

不是所有业务都需要高规格容灾。投资容灾前,要做合理的成本-收益评估:

业务类型不可用 1 小时的损失合理容灾投入
个人博客几乎零异地备份足矣
内部工具影响员工效率异地冷备
一般电商数十万同城主备 + 异地异步备
大型电商数百万到千万同城双活 + 异地热备
金融核心数千万+ + 合规处罚异地多活 + 强一致
关键基础设施难以估量多区域多活 + 持续演练

容灾投入的核心问题不是"我能做到多强",而是"我需要做到多强"。盲目追求"零 RTO 零 RPO"会让成本失控,反而拖垮整个系统经济性。

容灾投入的渐进路径

合理的容灾投入是随业务增长渐进的:

阶段 1:本地备份 + 监控告警           (启动期)
阶段 2:数据库主从 + 异地备份            (成长期)
阶段 3:同城主备 + 异地异步备             (扩展期)
阶段 4:同城双活 + 异地热备                (成熟期)
阶段 5:异地多活 + 完整演练体系            (大型化)

每一步都解决具体的容灾需求,不要跳过中间阶段直接上多活——多活的工程复杂度极高,小规模团队根本无法运维。

容灾的真正成本不是机器钱

成本类型内容
硬件异地机房、机器、网络专线
运维异地的部署、监控、变更同步
人力容灾团队、演练、应急响应
流程容灾流程的设计、文档、培训
业务适配应用层为容灾做的改造
演练时间定期演练对生产的影响
持续优化业务变化时容灾方案要跟着变

机器和带宽只是冰山一角,长期运营成本才是大头。这就是为什么"看起来便宜的容灾方案"在实际运营几年后,总成本可能超过预期数倍。