容灾演练:验证「从零恢复」到底要多久
备份最大的风险不是「没做」,而是「以为做了,真出事时才发现恢复不了」。唯一能验证的办法就是真的恢复一次。
一、两个必须搞清的指标
| 指标 | 含义 | 例子 |
|---|---|---|
| RPO | 恢复点目标:最多丢多少数据 | 每天备份一次 → RPO 约 24 小时 |
| RTO | 恢复时间目标:多久能恢复服务 | 演练测出来 40 分钟 |
问自己的问题:
- 能接受丢一天的数据吗?不能就得提高备份频率;
- 能接受停一小时吗?不能就得准备热备。
个人站点通常 RPO=24h、RTO=1h 就够了。
二、为什么必须演练
我遇到过的真实情况:
| 以为没问题 | 演练时发现 |
|---|---|
| 备份脚本在跑 | 早就因为权限问题失败了半年 |
| 数据库有 dump | dump 命令少了 --single-transaction,导出的表不一致 |
| 配置文件备份了 | 只备份了 /etc/nginx,漏了 /etc/letsencrypt |
| 异地有一份 | 异地那份已经 3 个月没更新 |
| 恢复很简单的 | 忘了数据库用户的密码 |
三、演练前的准备
先把文档写出来(演练本身就是在写文档):
恢复手册
1. 需要什么:新机器、备份文件、密钥、密码
2. 步骤:装系统 → 加固 → 装依赖 → 恢复配置 → 恢复数据 → 验证
3. 每一步预计耗时
4. 验证方法:访问哪些 URL、查哪些数据密码和密钥要单独安全存放(密码管理器),不能只存在服务器上——因为服务器可能就是那个挂掉的。
四、一次完整演练
建议开一台临时机器(按小时计费,几块钱),模拟「原机已死」。
第 0 步:计时开始
date > /tmp/dr-start.txt第 1 步:新机基础环境
# 装系统后
apt update && apt upgrade -y
apt install -y nginx mysql-server rsync curl git
# 目标:10 分钟内完成第 2 步:取回备份
# 从异地拉取最新备份
rsync -avz backup-host:/backups/baize/ /tmp/restore/
ls -lh /tmp/restore/
# 确认文件非空、时间是最近的这一步最容易发现问题:备份不存在、是空的、或者过期了。
第 3 步:恢复配置
tar xzf /tmp/restore/conf-*.tar.gz -C /
nginx -t
# 报证书路径错误?说明 /etc/letsencrypt 没备份到第 4 步:恢复数据
mysql -u root -p -e "CREATE DATABASE baize_db CHARACTER SET utf8mb4;"
gunzip < /tmp/restore/db-2026-06-24.sql.gz | mysql -u root -p baize_db
# 核对条数(和备份前记录的对比)
mysql -u root -p -e "SELECT COUNT(*) FROM baize_db.posts;"第 5 步:恢复站点文件
tar xzf /tmp/restore/www-*.tar.gz -C /var/www/
chown -R www-data:www-data /var/www/baize
systemctl reload nginx第 6 步:验证
curl -I https://www.bzii.cn
# 走查所有关键页面
# 登录后台、提交一次数据、检查写入是否正常第 7 步:计时结束
date
# 算出总耗时,就是 RTO 的真实值五、把过程自动化
演练熟了之后,把步骤写成脚本。真出事时你没心情一步步翻文档:
#!/usr/bin/env bash
# /opt/scripts/restore.sh <备份日期>
set -euo pipefail
STAMP="${1:-latest}"
SRC="/backups/baize"
echo "==> 恢复配置"
tar xzf "$SRC/conf-$STAMP.tar.gz" -C /
echo "==> 恢复站点"
tar xzf "$SRC/www-$STAMP.tar.gz" -C /var/www/
chown -R www-data:www-data /var/www/baize
echo "==> 恢复数据库"
read -rsp "MySQL root 密码: " PWD
gunzip < "$SRC/db-$STAMP.sql.gz" | mysql -u root -p"$PWD" baize_db
echo "==> 重载服务"
nginx -t && systemctl reload nginx
echo "恢复完成,请验证:curl -I https://www.bzii.cn"六、演练之后该改什么
每次演练都应该产出改进项。常见结论:
| 发现 | 改进 |
|---|---|
| 恢复耗时太长 | 把不变的依赖预装进镜像/快照 |
| 找密码花时间 | 密码统一放进密码管理器 |
| 忘了某个配置目录 | 扩充备份清单 |
| 备份版本不确定 | 备份文件名带时间戳 + 记录 latest |
| 手工步骤多 | 写成脚本 |
七、用快照加速
如果云厂商支持快照,最简单高效的方案是:
- 装好所有依赖、加固完成后打一份系统盘快照(黄金镜像);
- 日常只备份变化的数据(站点文件 + 数据库 + 少量配置);
- 恢复时:从快照开机 → 恢复数据 → 完成。
这样 RTO 能从 40 分钟降到 10 分钟,因为「装系统 + 装依赖 + 加固」那部分全省了。
# 数据备份保持高频(每天),快照保持低频(每月或版本变更时)八、演练频率
| 场景 | 建议频率 |
|---|---|
| 个人站点 | 半年一次 |
| 有用户的服务 | 每季度一次 |
| 核心业务 | 每月一次 |
| 每次架构变更后 | 立即演练一次 |
九、检查清单
- 有书面的恢复步骤
- 密码/密钥在服务器之外有备份
- 知道备份文件在哪、怎么取
- 数据核对方法明确(查哪张表、对哪个数)
- 演练过至少一次,知道 RTO 是多少
- 备份脚本有失败告警
# 备份脚本最后加一句,失败时能发现
if [ $? -ne 0 ]; then echo "备份失败!" | mail -s "backup failed" you@example.com; fi没演练过的备份,只能算「看起来有备份」。花两小时演练一次,换来的是真出事时不慌。
