Skip to content

备份与恢复

概述

定期备份是防止数据丢失的最后防线。本文介绍 MySQL 数据库备份、Redis 数据备份、上传文件备份的方案,以及自动化备份调度和恢复操作。

备份策略 3-2-1 原则

  • 3 份数据副本(1 份生产 + 2 份备份)
  • 2 种不同存储介质(如本地磁盘 + 远程存储)
  • 1 份异地备份(防机房级灾难)

MySQL 数据库备份

全量备份

bash
# 使用 mysqldump 备份单个数据库
mysqldump -h 127.0.0.1 -u root -p --single-transaction \
    --routines --triggers --events \
    djangoadmin_prod > backup_$(date +%Y%m%d_%H%M%S).sql

# 压缩备份
mysqldump -h 127.0.0.1 -u root -p --single-transaction \
    djangoadmin_prod | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz

--single-transaction 作用

--single-transaction 参数确保 InnoDB 表的备份一致性,不锁表,不影响线上服务。

增量备份

基于 MySQL binlog 实现增量备份:

bash
# 查看当前 binlog 位置
mysql -u root -p -e "SHOW MASTER STATUS;"

# 备份 binlog
mysqlbinlog --start-datetime="2026-09-05 00:00:00" \
 mysql-bin.000001 > binlog_incremental.sql

binlog 配置

确保 MySQL 配置中启用了 binlog:

ini
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
expire_logs_days = 7

仅备份表结构

bash
# 仅备份结构(不含数据)
mysqldump -h 127.0.0.1 -u root -p --no-data \
 djangoadmin_prod > schema_$(date +%Y%m%d).sql

Redis 数据备份

RDB 快照

bash
# 手动触发 RDB 快照
redis-cli BGSAVE

# 查看最后一次快照时间
redis-cli LASTSAVE

# 复制 RDB 文件
cp /var/lib/redis/dump.rdb /data/backup/redis_$(date +%Y%m%d).rdb

AOF 持久化

bash
# redis.conf 配置
appendonly yes
appendfsync everysec

# 备份 AOF 文件
cp /var/lib/redis/appendonly.aof /data/backup/redis_$(date +%Y%m%d).aof

Redis 备份建议

Redis 用于缓存和 token 黑名单,数据可从数据库重建。建议使用 RDB 快照即可,AOF 可选。

上传文件备份

bash
# 打包上传目录
tar -czf uploads_$(date +%Y%m%d).tar.gz /data/apps/uploads/

# 使用 rsync 增量同步到远程
rsync -avz --delete /data/apps/uploads/ backup@10.0.2.100:/data/backup/uploads/

自动化备份

备份脚本

创建 /data/scripts/backup.sh

bash
#!/bin/bash
# 备份目录
BACKUP_DIR="/data/backup"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7

# 创建备份目录
mkdir -p ${BACKUP_DIR}/{mysql,redis,uploads}

# MySQL 备份
mysqldump -h 127.0.0.1 -u djangoadmin -p'<密码>' \
 --single-transaction djangoadmin_prod | gzip > \
 ${BACKUP_DIR}/mysql/backup_${DATE}.sql.gz

# Redis 备份
redis-cli BGSAVE
sleep 5
cp /var/lib/redis/dump.rdb ${BACKUP_DIR}/redis/redis_${DATE}.rdb

# 上传文件备份
tar -czf ${BACKUP_DIR}/uploads/uploads_${DATE}.tar.gz /data/apps/uploads/

# 清理过期备份
find ${BACKUP_DIR} -type f -mtime +${RETENTION_DAYS} -delete

echo "[$(date)] Backup completed" >> /var/log/backup.log

Crontab 配置

bash
# 编辑定时任务
crontab -e

# 每天凌晨 2 点执行备份
0 2 * * * /bin/bash /data/scripts/backup.sh >> /var/log/backup.log 2>&1

# 每周日凌晨 3 点执行全量备份
0 3 * * 0 /bin/bash /data/scripts/backup_full.sh >> /var/log/backup.log 2>&1

Crontab 说明

分 时 日 月 周 命令
0 2 * * * /bin/bash /data/scripts/backup.sh
│ │ │ │ │
│ │ │ │ └── 星期几 (0-7, 0和7都是周日)
│ │ │ └──── 月份 (1-12)
│ │ └─────── 日 (1-31)
│ └────────── 时 (0-23)
└───────────── 分 (0-59)

数据恢复

MySQL 恢复

bash
# 从 SQL 文件恢复
mysql -h 127.0.0.1 -u root -p djangoadmin_prod < backup_20260905.sql

# 从压缩文件恢复
gunzip < backup_20260905.sql.gz | mysql -h 127.0.0.1 -u root -p djangoadmin_prod

Redis 恢复

bash
# 停止 Redis
redis-cli SHUTDOWN NOSAVE

# 替换 RDB 文件
cp /data/backup/redis/redis_20260905.rdb /var/lib/redis/dump.rdb

# 启动 Redis
redis-server /etc/redis/redis.conf

上传文件恢复

bash
# 解压恢复
tar -xzf uploads_20260905.tar.gz -C /

恢复演练

重要

定期进行恢复演练,验证备份文件的完整性和可用性。建议每季度至少演练一次。

bash
# 恢复演练步骤
# 1. 在测试环境创建空库
mysql -u root -p -e "CREATE DATABASE djangoadmin_restore;"

# 2. 恢复备份
mysql -u root -p djangoadmin_restore < backup_20260905.sql

# 3. 验证数据完整性
mysql -u root -p -e "
 SELECT 'user' AS tbl, COUNT(*) AS cnt FROM djangoadmin_restore.fastapi_user
 UNION ALL
 SELECT 'article', COUNT(*) FROM djangoadmin_restore.fastapi_article;
"

# 4. 清理测试库
mysql -u root -p -e "DROP DATABASE djangoadmin_restore;"

备份监控

bash
# 检查备份文件是否存在且非空
find /data/backup/mysql -name "*.sql.gz" -mtime -1 -size +0 | wc -l
# 返回 0 则告警

# 检查备份文件大小
ls -lh /data/backup/mysql/backup_$(date +%Y%m%d)*.sql.gz

总结

备份方案覆盖 MySQL(mysqldump 全量 + binlog 增量)、Redis(RDB 快照)、上传文件(tar 打包 + rsync 同步)。通过 Crontab 实现自动化调度,保留最近 7 天备份。关键要点:备份文件异地存储、定期恢复演练验证完整性、监控备份任务执行状态。

小蚂蚁云团队 · 提供技术支持