备份不是拷贝:先算清 RTO 与 RPO
「我们每天都备份」这句话,在事故现场常常撑不过五分钟。真正要先回答的不是「备没备」,而是出了事之后,业务能容忍多久、丢多少。两个参数把这件事说清楚:
- RTO(恢复时间目标):系统挂掉后,业务能容忍停摆多久?五分钟、两小时、还是一晚上?RTO 决定了你的容灾是要「自动秒级切换」还是「人工过夜恢复」。
- RPO(恢复点目标):能容忍丢多长时间的数据?RPO 等于零意味着必须实时同步;RPO 等于一天意味着每天备一次就够。
| 业务类型 | 典型 RTO | 典型 RPO | 备份策略取向 |
|---|---|---|---|
| 核心交易支付 | < 5 分钟 | ≈ 0 | 双机房实时同步,自动切换 |
| 一般业务系统 | 1~4 小时 | ≤ 15 分钟 | 主从 + 定期 binlog 备份 |
| 内部工具 / 文档站 | 24 小时 | ≤ 24 小时 | 每日全量 + 异地副本即可 |
备份策略是业务定价的函数。给内部文档站做双活,和给支付系统只做每日备份,都是浪费——前者浪费钱,后者赌命。
- 先定目标RTO 决定切换自动化程度,RPO 决定备份频率,别倒过来。
- 3-2-1三份副本、两种介质、一份异地,是备份策略的底线。
- 恢复验证备份的价值由「能不能真的恢复」定义,备份本身不算数。
- 演练定期做真实切换,预案只在第一次读它时才暴露出问题。
3-2-1 策略:经典原则的现代落地
3-2-1 是备份领域被念叨了几十年的黄金原则,到云时代依然成立,只是介质变了:
- 3 份数据副本:一份生产数据,两份备份。单副本在磁盘故障面前等于没有。
- 2 种不同介质:别把两份备份都放在同一块盘、同一块 RAID、同一台虚拟化平台上。
- 1 份异地:另一份备份放在物理上远离主机房的地方——跨可用区、跨城市、甚至对象存储归档,防机房级灾难。
现代云环境下最常见的落地形态是:生产主库 → 同地域从库(热备) → 每日快照跨区域复制到对象存储(异地冷备)。三层各有各的恢复速度,覆盖不同事故半径:
| 层级 | 形态 | 应对事故 | 恢复速度 |
|---|---|---|---|
| 热备层 | 主从同步 / 多副本 | 单机故障、主库宕机 | 秒级~分钟级切换 |
| 快照层 | 每日 / 每小时快照 | 误删数据、逻辑错误 | 十几分钟~小时级回滚 |
| 异地冷备层 | 对象存储归档副本 | 机房级灾难、勒索病毒 | 小时级~天级恢复 |
全量、增量与差异:备份类型怎么选
备份类型的选择本质是在「备份窗口」和「恢复速度」之间做权衡:
- 全量备份:每次都完整备份一遍。恢复最简单——只需一份;但耗时、占空间,每天对 1TB 数据做全量往往不现实。
- 增量备份:只备份「上次备份之后变化的部分」。快、省空间;但恢复时要先还原全量、再依次回放每一份增量,链条长、任何一环损坏就断档。
- 差异备份:只备份「上次全量之后变化的部分」。介于两者之间——恢复只需要全量 + 最近一份差异。
# 典型组合:周日全量 + 每天增量,保留 4 周
# 恢复路径:周日全量 → 周一增量 → 周二增量 → … → 故障前一天
# 风险:链条上任何一份增量损坏,之后的数据就回不去了
# 更稳的组合:每日差异,每周全量
# 恢复路径:最近一次全量 → 最近一份差异(只需两步)
# 代价:每天的差异体量会比纯增量大一些
数据库领域的实践和文件备份略不同:全量快照 + 持续归档日志(binlog / WAL)是更主流的方案。快照给你一致性基准点,归档日志让你把数据回放到任意秒级时间点——也就是时间点恢复(PITR)。误删一张表?不用整库回到昨天,回放日志把时间点定在误删前一秒即可。
容灾等级:从冷备到双活
备份解决「数据不丢」,容灾解决「服务不停」。容灾有几个常见等级,按投入和恢复速度递增:
- 冷备:备用数据定期复制到异地,但那边平时没有运行中的服务。出事时才从零拉起环境,RTO 以小时甚至天计。便宜,适合非核心系统。
- 温备:异地有一套热着的、数据同步中的备用环境,但不接流量。切换时只需把流量切过去,RTO 降到分钟级。
- 热备 / 主从:主备双活数据实时同步,备机可以随时顶上来,配合负载均衡做秒级切换。
- 双活 / 多活:两个机房同时对外提供服务,数据双向同步。RTO 接近零,但数据一致性和脑裂处理复杂度指数级上升。
对绝大多数中小团队,温备是性价比拐点:不用像双活那样解决双向同步和冲突,但又比冷备多了一套平时就能跑的备用环境。云厂商的跨可用区主从 + 自动故障切换,基本就是这个档位。
演练为王:没切换过的备份等于没有备份
行业里流传一句话:「没恢复过的备份不叫备份,叫希望。」事故复盘里反复出现的剧本是:监控显示备份任务每天都绿色打勾,真到恢复时才发现——备份脚本三个月前就因为权限问题悄悄失败了,或者恢复出来的数据库版本和线上对不上,又或者归档文件在对象存储上根本没复制成功。
演练要解决三类问题:
- 完整性问题:备份任务到底有没有真的成功?加密的备份能不能解出来?文件能不能完整校验?
- 流程性问题:恢复要多久?步骤有没有文档?谁有权限?依赖的其他服务怎么拉起?
- 人的问题:真出事时值班人按预案操作过吗,还是第一次见这份预案?
建议的节奏:每季度一次恢复演练——挑一个真实备份,在隔离环境里完整恢复一遍,记录耗时与踩坑;每半年一次切换演练——真实地把流量切到备机房,再切回来。演练本身要安排在业务低峰,且提前通知相关方。
演练不是彩排,是验收。第一次读预案往往是在事故现场——那次就是最贵的一次。
数据库与容器环境的备份要点
两类最常被备份的对象,各有自己的坑:
数据库——别用文件级拷贝糊弄。直接复制数据文件在数据库运行时往往是不一致的,必须用官方工具做一致性快照:
# MySQL:物理备份(Percona XtraBackup),热备不锁表
xtrabackup --backup --target-dir=/backup/mysql-full --user=backup
# PostgreSQL:基础备份 + WAL 归档,支持任意时间点恢复
pg_basebackup -D /backup/pg-base -Ft -z
# 配合 archive_command 持续归档 WAL 段
# 关键纪律:备份文件加密后再传对象存储,别让生产裸数据满天飞
容器环境——容器本身是无状态的,真正要备的是数据卷里的东西和编排配置:
- 数据库容器的挂载卷,按上面数据库方式备份。
- Kubernetes 的 Deployment / StatefulSet 清单导出成 YAML 入 Git——配置即代码,本身就是最好的「备份」。
- etcd 集群定期快照:它存着整个集群的状态,etcd 没了集群就没了。
一次完整的故障切换演练清单
把上面所有原则落成一张可以照着打勾的清单。建议每次演练前打印一份,事后归档:
| 阶段 | 动作 | 通过标准 |
|---|---|---|
| 演练前 | 通知相关方、冻结发布、选定时间窗 | 人人知道今天要切,不在变更窗口 |
| 验证备份 | 随机抽一份最新备份做完整性校验 | 校验通过,可正常解密 |
| 切换流量 | 把入口流量从主机房切到备机房 | 核心接口在备机房健康检查全绿 |
| 业务验证 | 走一遍下单、支付、登录主链路 | 关键交易成功率与平时一致 |
| 数据对账 | 比对切换期间有无数据丢失或不一致 | 实际数据损失 ≤ RPO |
| 切回 | 按预案把流量切回主机房 | 切回过程无二次故障 |
| 复盘 | 记录实际 RTO/RPO、卡点、预案缺口 | 产出改进项并排期修复 |
记住一个朴素的判断标准:你的备份策略值多少钱,取决于你愿意多久演练一次它。日常把 RTO/RPO 定清楚、按 3-2-1 把副本铺开、每季度真刀真枪恢复一次,真出机房级事故那天,你会庆幸自己练过——而不是第一次翻预案。