深色模式
备份与容灾基础:3-2-1 原则落地
摘要:没有验证过的备份不算备份。本文按 3-2-1 原则(3 份副本、2 种介质、1 份异地)设计备份体系,给出自动化脚本、加密方式、RPO/RTO 定义与恢复演练流程。
适用环境
bash
cat /etc/os-release
command -v rsync && rsync --version | head -1
command -v mysqldump && mysqldump --version
command -v restic && restic version
df -h /backup1
2
3
4
5
2
3
4
5
操作步骤
1. 先定义两个指标,否则无法设计方案
- RPO(恢复点目标):最多容忍丢多少数据。例如 15 分钟。
- RTO(恢复时间目标):最多容忍多久恢复服务。例如 2 小时。
RPO 决定备份频率,RTO 决定恢复方式(冷备/热备/多活)。
2. 理解 3-2-1
| 项 | 含义 | 落地示例 |
|---|---|---|
| 3 份 | 数据至少 3 个副本 | 生产数据 + 本地备份 + 异地备份 |
| 2 种介质 | 至少 2 种存储介质 | 本地磁盘 + 对象存储 |
| 1 份异地 | 至少 1 份在异地/离线 | 跨地域对象存储或离线副本 |
再加一条现代补充:至少 1 份不可变(对象锁/WORM),以对抗勒索软件。
3. 数据库备份脚本
bash
cat >/usr/local/bin/backup-mysql.sh <<'EOF'
#!/bin/bash
set -euo pipefail
DATE=$(date +%F-%H%M)
DIR=/backup/mysql/$DATE
mkdir -p "$DIR"
# 逻辑备份(一致性)
mysqldump --single-transaction --quick --routines --triggers \
--set-gtid-purged=OFF --all-databases > "$DIR/all.sql"
# 校验
[ -s "$DIR/all.sql" ] || { echo "备份文件为空,失败"; exit 1; }
# 压缩 + 加密(口令从文件读取,不要写命令行)
tar czf - -C "$DIR" all.sql \
| gpg --symmetric --cipher-algo AES256 --batch \
--passphrase-file /etc/backup.key -o "$DIR/all.sql.tar.gz.gpg"
rm -f "$DIR/all.sql"
sha256sum "$DIR/all.sql.tar.gz.gpg" > "$DIR/SHA256SUMS"
# 清理 14 天前
find /backup/mysql -maxdepth 1 -mtime +14 -type d -exec rm -rf {} +
echo "backup ok: $DIR"
EOF
chmod +x /usr/local/bin/backup-mysql.sh1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
4. 文件备份:restic(去重 + 加密 + 多后端)
bash
restic init --repo /backup/restic-repo --password-file /etc/restic.key
cat >/usr/local/bin/backup-files.sh <<'EOF'
#!/bin/bash
set -euo pipefail
export RESTIC_PASSWORD_FILE=/etc/restic.key
restic -r /backup/restic-repo backup /data /etc --tag "$(hostname)" \
--exclude='*.tmp' --exclude='/data/cache'
restic -r /backup/restic-repo forget --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
restic -r /backup/restic-repo check --read-data-subset=5%
EOF
chmod +x /usr/local/bin/backup-files.sh1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
5. 异地副本:同步到对象存储
bash
cat >/usr/local/bin/backup-offsite.sh <<'EOF'
#!/bin/bash
set -euo pipefail
# 本地 → 异地对象存储(桶需开启版本控制与对象锁)
aws s3 sync /backup/mysql s3://backup-bucket/mysql/ \
--sse aws:kms --storage-class STANDARD_IA
# restic 也支持直接把 repo 放对象存储
# restic -r s3:s3.amazonaws.com/backup-bucket/restic init
EOF
chmod +x /usr/local/bin/backup-offsite.sh1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
异地同步账号权限过大是新的风险点
只授予 PutObject + 桶内限定前缀,不要给 DeleteObject,否则勒索软件可沿同步链路删除备份。
6. 定时执行与监控
bash
cat >/etc/cron.d/backup <<'EOF'
0 2 * * * root /usr/local/bin/backup-mysql.sh >> /var/log/backup.log 2>&1
30 2 * * * root /usr/local/bin/backup-files.sh >> /var/log/backup.log 2>&1
0 4 * * * root /usr/local/bin/backup-offsite.sh >> /var/log/backup.log 2>&1
EOF1
2
3
4
5
2
3
4
5
监控要点(必须有告警):
- 备份任务是否成功(退出码 + 日志关键字)。
- 最近一次成功备份距今时长(新鲜度)。
- 备份容量与增长率。
bash
grep -c "backup ok" /var/log/backup.log
find /backup/mysql -maxdepth 1 -mtime -1 -type d | wc -l
du -sh /backup/* | tail -51
2
3
2
3
7. 恢复演练:备份的唯一验收标准
bash
cat >/usr/local/bin/restore-drill.sh <<'EOF'
#!/bin/bash
set -euo pipefail
LATEST=$(ls -1dt /backup/mysql/*/ | head -1)
WORK=/tmp/restore-drill-$(date +%s)
mkdir -p "$WORK"
gpg --decrypt --batch --passphrase-file /etc/backup.key \
"$LATEST/all.sql.tar.gz.gpg" | tar xz -C "$WORK"
sha256sum -c "$LATEST/SHA256SUMS" --ignore-missing --status 2>/dev/null || true
# 起一个临时实例做恢复验证(不要直接灌生产!)
docker run -d --name drill-db -e MYSQL_ROOT_PASSWORD=drillpass \
-v "$WORK":/docker-entrypoint-initdb.d -P mysql:8.0
echo "等待实例就绪后执行: docker exec drill-db mysql -uroot -pdrillpass -e 'SHOW DATABASES;'"
EOF
chmod +x /usr/local/bin/restore-drill.sh1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
演练频率建议:每季度一次完整恢复演练,记录实际 RTO 并与目标对比。
8. 灾备等级速查
| 等级 | 特点 | RTO 量级 |
|---|---|---|
| 冷备 | 只有备份,恢复需重建 | 小时~天 |
| 温备 | 备用环境已建,数据需恢复 | 数十分钟 |
| 热备 | 主从同步,可切换 | 分钟 |
| 多活 | 多地域同时服务 | 秒~分钟 |
验证
bash
ls -1dt /backup/mysql/*/ | head -3
restic -r /backup/restic-repo snapshots --latest 3
restic -r /backup/restic-repo check
# 校验加密备份可解密
gpg --decrypt --batch --passphrase-file /etc/backup.key \
"$(ls -1dt /backup/mysql/*/ | head -1)/all.sql.tar.gz.gpg" | tar tzf - | head -3
# 异地副本存在
aws s3 ls s3://backup-bucket/mysql/ --recursive | tail -31
2
3
4
5
6
7
8
2
3
4
5
6
7
8
判定标准:每日备份成功告警可见;异地副本存在且不可被单点删除;最近一次恢复演练有记录且 RTO 达标。
常见坑
从未做过恢复演练
这是最普遍也最致命的问题。备份成功 ≠ 可恢复,必须定期真恢复一次。
备份与生产在同一块盘/同一主机
主机损毁或勒索加密时一并丢失。必须异地 + 不同介质。
同步账号有删除权限
勒索软件会顺着同步链路删掉备份。使用只写账号 + 对象锁 + 版本控制。
备份不加密
备份介质往往权限更松,等于数据外泄的捷径。必须加密并单独管理密钥。
只备份数据不备份配置与密钥
恢复时缺 my.cnf、应用配置、证书私钥,照样起不来。备份范围要包含配置。