# 备份与恢复 ## 概述 定期备份是防止数据丢失的最后防线。本文介绍 MySQL 数据库备份、Redis 数据备份、上传文件备份的方案,以及自动化备份调度和恢复操作。 :::tip 备份策略 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 ``` :::tip --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 ``` :::tip 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 ``` :::tip 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 ``` :::tip 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 / ``` ## 恢复演练 :::warning 重要 定期进行恢复演练,验证备份文件的完整性和可用性。建议每季度至少演练一次。 ::: ```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.tornado_user UNION ALL SELECT 'article', COUNT(*) FROM djangoadmin_restore.tornado_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 天备份。关键要点:备份文件异地存储、定期恢复演练验证完整性、监控备份任务执行状态。