容灾演练:验证「从零恢复」到底要多久

备份最大的风险不是「没做」,而是「以为做了,真出事时才发现恢复不了」。唯一能验证的办法就是真的恢复一次。

一、两个必须搞清的指标

指标含义例子
RPO恢复点目标:最多丢多少数据每天备份一次 → RPO 约 24 小时
RTO恢复时间目标:多久能恢复服务演练测出来 40 分钟

问自己的问题:

  • 能接受丢一天的数据吗?不能就得提高备份频率;
  • 能接受停一小时吗?不能就得准备热备。

个人站点通常 RPO=24h、RTO=1h 就够了。

二、为什么必须演练

我遇到过的真实情况:

以为没问题演练时发现
备份脚本在跑早就因为权限问题失败了半年
数据库有 dumpdump 命令少了 --single-transaction,导出的表不一致
配置文件备份了只备份了 /etc/nginx,漏了 /etc/letsencrypt
异地有一份异地那份已经 3 个月没更新
恢复很简单的忘了数据库用户的密码

三、演练前的准备

先把文档写出来(演练本身就是在写文档):

txt
恢复手册
1. 需要什么:新机器、备份文件、密钥、密码
2. 步骤:装系统 → 加固 → 装依赖 → 恢复配置 → 恢复数据 → 验证
3. 每一步预计耗时
4. 验证方法:访问哪些 URL、查哪些数据

密码和密钥要单独安全存放(密码管理器),不能只存在服务器上——因为服务器可能就是那个挂掉的。

四、一次完整演练

建议开一台临时机器(按小时计费,几块钱),模拟「原机已死」。

第 0 步:计时开始

bash
date > /tmp/dr-start.txt

第 1 步:新机基础环境

bash
# 装系统后
apt update && apt upgrade -y
apt install -y nginx mysql-server rsync curl git
# 目标:10 分钟内完成

第 2 步:取回备份

bash
# 从异地拉取最新备份
rsync -avz backup-host:/backups/baize/ /tmp/restore/
ls -lh /tmp/restore/
# 确认文件非空、时间是最近的

这一步最容易发现问题:备份不存在、是空的、或者过期了。

第 3 步:恢复配置

bash
tar xzf /tmp/restore/conf-*.tar.gz -C /
nginx -t
# 报证书路径错误?说明 /etc/letsencrypt 没备份到

第 4 步:恢复数据

bash
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 步:恢复站点文件

bash
tar xzf /tmp/restore/www-*.tar.gz -C /var/www/
chown -R www-data:www-data /var/www/baize
systemctl reload nginx

第 6 步:验证

bash
curl -I https://www.bzii.cn
# 走查所有关键页面
# 登录后台、提交一次数据、检查写入是否正常

第 7 步:计时结束

bash
date
# 算出总耗时,就是 RTO 的真实值

五、把过程自动化

演练熟了之后,把步骤写成脚本。真出事时你没心情一步步翻文档:

bash
#!/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
手工步骤多写成脚本

七、用快照加速

如果云厂商支持快照,最简单高效的方案是:

  1. 装好所有依赖、加固完成后打一份系统盘快照(黄金镜像);
  2. 日常只备份变化的数据(站点文件 + 数据库 + 少量配置);
  3. 恢复时:从快照开机 → 恢复数据 → 完成。

这样 RTO 能从 40 分钟降到 10 分钟,因为「装系统 + 装依赖 + 加固」那部分全省了。

bash
# 数据备份保持高频(每天),快照保持低频(每月或版本变更时)

八、演练频率

场景建议频率
个人站点半年一次
有用户的服务每季度一次
核心业务每月一次
每次架构变更后立即演练一次

九、检查清单

  • 有书面的恢复步骤
  • 密码/密钥在服务器之外有备份
  • 知道备份文件在哪、怎么取
  • 数据核对方法明确(查哪张表、对哪个数)
  • 演练过至少一次,知道 RTO 是多少
  • 备份脚本有失败告警
bash
# 备份脚本最后加一句,失败时能发现
if [ $? -ne 0 ]; then echo "备份失败!" | mail -s "backup failed" you@example.com; fi

没演练过的备份,只能算「看起来有备份」。花两小时演练一次,换来的是真出事时不慌。