# 灾备计划 (Disaster Recovery Plan) > **文档版本**: 1.0 > **最后更新**: 2026-06-17 > **审核周期**: 每季度审核一次 --- ## 1. 概述 本文档定义了 Next_Edu 系统的灾备策略、恢复目标、备份方案和故障切换流程,确保在发生灾难性故障时能够快速恢复服务并最小化数据丢失。 ### 1.1 适用范围 - 生产环境数据库(MySQL) - 应用服务(Next.js) - 备份文件(本地 + 异地) - CI/CD 流水线 ### 1.2 关键指标 | 指标 | 目标 | 说明 | |------|------|------| | **RTO** (Recovery Time Objective) | 4 小时 | 从故障发生到服务恢复的最长时间 | | **RPO** (Recovery Point Objective) | 24 小时 | 最大可接受的数据丢失时间窗口 | --- ## 2. RTO/RPO 定义 ### 2.1 RTO(恢复时间目标): 4 小时 **定义**: 从系统故障发生到服务完全恢复的最长允许时间。 **分解**: | 阶段 | 预计耗时 | 说明 | |------|---------|------| | 故障检测 | 5 分钟 | 健康检查脚本自动检测 | | 通知与决策 | 15 分钟 | 通知运维团队,决定是否切换 | | 执行恢复 | 60 分钟 | 从备份恢复数据库 | | 应用重启 | 10 分钟 | 重启应用并验证 | | 数据验证 | 30 分钟 | 验证数据完整性 | | 流量恢复 | 10 分钟 | 逐步恢复用户流量 | | 缓冲时间 | 90 分钟 | 应对意外情况 | | **总计** | **≤ 4 小时** | | ### 2.2 RPO(恢复点目标): 24 小时 **定义**: 最大可接受的数据丢失时间窗口。 **保障措施**: - 每日凌晨 2 点全量备份(cron: `0 2 * * *`) - 备份后自动校验完整性 - 备份后自动同步到异地存储 - 最坏情况下丢失不超过 24 小时数据 --- ## 3. 备份策略 ### 3.1 备份频率 | 备份类型 | 频率 | 时间 | 保留期 | |---------|------|------|--------| | 全量备份 | 每日 | 凌晨 2:00 (CST) | 本地 30 天,异地 90 天 | | 异地同步 | 每日(备份后) | 凌晨 2:30 (CST) | 90 天 | ### 3.2 备份内容 - **数据库**: 使用 `mysqldump` 导出全部数据库,`gzip` 压缩 - **格式**: `db_backup_YYYYMMDD_HHMMSS.sql.gz` - **存储位置**: - 本地: `./backups/` - 异地: S3/OSS/NFS(根据 `BACKUP_OFFSITE_BACKEND` 配置) ### 3.3 备份验证 每次备份后自动执行校验: 1. 文件存在性检查 2. 文件大小检查(最小 1KB) 3. gzip 完整性校验(`gunzip -t`) 4. SQL 内容结构检查(mysqldump 头部、语句数量) 5. SQL 语法校验(可选,需 `DATABASE_URL`) ### 3.4 备份保留策略 | 存储位置 | 保留期 | 清理方式 | |---------|--------|---------| | 本地 (`./backups/`) | 30 天 | `find -mtime +30 -delete` | | 异地 (S3/OSS/NFS) | 90 天 | `backup-offsite-sync.sh` 自动清理 | --- ## 4. 故障切换流程 ### 4.1 故障检测 1. **自动检测**: `health-check.sh` 定期运行,检查: - 应用 HTTP 健康端点 - 数据库连接 - 磁盘空间 - 备份新鲜度 2. **手动报告**: 用户反馈、监控系统告警 ### 4.2 故障切换步骤 ``` ┌─────────────────┐ │ 1. 检测故障 │ 健康检查失败 / 用户报告 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 2. 通知运维 │ 电话/邮件/即时通讯通知运维团队 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 3. 决策(5分钟) │ 评估故障严重程度,决定是否切换 └────────┬────────┘ │ ┌────┴────┐ │ │ 切换 不切换 │ │ ▼ ▼ ┌─────────┐ ┌─────────┐ │4. 执行 │ │ 修复主库 │ │ 切换 │ │ │ └────┬────┘ └─────────┘ │ ▼ ┌─────────┐ │5. 验证 │ 健康检查、功能测试 │ 恢复 │ └────┬────┘ │ ▼ ┌─────────┐ │6. 事后 │ 记录事件、复盘改进 │ 复盘 │ └─────────┘ ``` ### 4.3 执行故障切换 使用 `failover.sh` 脚本: ```bash # 手动模式(交互式确认) ./scripts/failover.sh # 半自动模式(检测到故障后自动切换,需确认) ./scripts/failover.sh --auto # 演练模式(不实际执行) ./scripts/failover.sh --dry-run # 指定备库 ./scripts/failover.sh --standby "mysql://user:pass@standby-host:3306/dbname" ``` **前提条件**: - 配置 `DATABASE_URL_STANDBY` 环境变量 - 备库已配置主从复制(如果是主从架构) - 应用容器可通过 Docker 重启 --- ## 5. 灾备演练 ### 5.1 演练频率 | 演练类型 | 频率 | 触发方式 | |---------|------|---------| | 自动演练 | 每周一次 | CI 定时任务(每周一凌晨 4 点) | | 手动演练 | 每月一次 | 运维人员手动触发 | | 全量演练 | 每季度一次 | 完整故障切换演练 | ### 5.2 演练内容 1. **创建测试数据库** (`next_edu_dr_drill`) 2. **从最新备份恢复** 到测试数据库 3. **数据完整性检查**: - 表数量对比(测试库 vs 源库) - 记录数对比 4. **冒烟测试**: - 基础表查询 - 关键业务表查询(users, schools) 5. **清理测试数据库** 6. **生成演练报告** ### 5.3 演练脚本 ```bash # Bash 版本(Linux/macOS) ./scripts/dr-drill.sh # PowerShell 版本(Windows) .\scripts\dr-drill.ps1 # 指定备份文件 ./scripts/dr-drill.sh --backup backups/db_backup_20260617_020000.sql.gz # 保留测试数据库(用于调试) ./scripts/dr-drill.sh --no-cleanup ``` ### 5.4 演练报告 - **存储位置**: `docs/dr/reports/` - **格式**: Markdown - **内容**: 演练时间、步骤结果、RTO 评估、数据完整性指标 - **保留期**: 90 天(CI artifact) --- ## 6. 联系人列表 > **注意**: 以下为模板,请根据实际人员填写 ### 6.1 主要联系人 | 角色 | 姓名 | 电话 | 邮箱 | 职责 | |------|------|------|------|------| | 主负责人 | [待填写] | [待填写] | [待填写] | 灾备决策、协调 | | 备份负责人 | [待填写] | [待填写] | [待填写] | 备份执行、监控 | | DBA | [待填写] | [待填写] | [待填写] | 数据库恢复 | | 运维工程师 | [待填写] | [待填写] | [待填写] | 应用部署、网络 | | 开发负责人 | [待填写] | [待填写] | [待填写] | 代码修复、功能验证 | ### 6.2 升级路径 1. **L1**: 运维工程师(5 分钟内响应) 2. **L2**: 主负责人 + DBA(15 分钟内响应) 3. **L3**: 全体联系人(30 分钟内响应) --- ## 7. 恢复步骤 ### 7.1 从备份恢复数据库 ```bash # 1. 获取最新备份 LATEST_BACKUP=$(ls -t backups/db_backup_*.sql.gz | head -1) echo "Using backup: $LATEST_BACKUP" # 2. 校验备份完整性 ./scripts/backup-verify.sh "$LATEST_BACKUP" # 3. 恢复数据库 ./scripts/restore-db.sh "$LATEST_BACKUP" # 4. 验证恢复结果 mysql -u root -p -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='next_edu';" ``` ### 7.2 完整恢复流程 1. **获取最新备份** - 本地: `./backups/` - 异地: 从 S3/OSS/NFS 下载 - CI artifact: 从 Gitea Actions 下载 2. **恢复数据库** ```bash ./scripts/restore-db.sh backups/db_backup_YYYYMMDD_HHMMSS.sql.gz ``` 3. **重启应用** ```bash docker restart nextjs-app # 或 docker stop nextjs-app && docker rm nextjs-app # 重新部署 ``` 4. **验证数据完整性** ```bash # 运行健康检查 ./scripts/health-check.sh # 运行灾备演练(对比数据) ./scripts/dr-drill.sh --no-cleanup ``` 5. **恢复流量** - 验证应用功能正常 - 逐步恢复用户流量 - 监控系统指标 --- ## 8. 监控与告警 ### 8.1 健康检查 ```bash # 手动运行健康检查 ./scripts/health-check.sh # 输出 JSON 格式报告 ./scripts/health-check.sh > health-report.json ``` **检查项**: - 应用 HTTP 健康端点 - 数据库连接 - 磁盘空间(阈值 90%) - 备份新鲜度(24 小时内) ### 8.2 告警条件 | 条件 | 严重级别 | 通知方式 | |------|---------|---------| | 应用不可达 | 严重 | 电话 + 邮件 | | 数据库连接失败 | 严重 | 电话 + 邮件 | | 磁盘空间 > 90% | 警告 | 邮件 | | 备份超过 24 小时 | 警告 | 邮件 | | 备份校验失败 | 严重 | 电话 + 邮件 | | 灾备演练失败 | 警告 | 邮件 | --- ## 9. 环境变量配置 ```bash # 灾备配置 BACKUP_OFFSITE_BACKEND=none # s3|oss|nfs|none BACKUP_OFFSITE_REMOTE= # 远程路径 BACKUP_OFFSITE_BUCKET= # 存储桶名 BACKUP_OFFSITE_ACCESS_KEY= # 访问密钥 BACKUP_OFFSITE_SECRET_KEY= # 秘密密钥 BACKUP_OFFSITE_REGION=us-east-1 # 区域 DR_DRILL_TEST_DB=next_edu_dr_drill # 演练测试数据库 HEALTH_CHECK_URL=http://localhost:8015 # 健康检查 URL # 故障切换配置 DATABASE_URL_STANDBY= # 备库连接 URL FAILOVER_APP_NAME=nextjs-app # 应用容器名 FAILOVER_APP_URL=http://localhost:8015 # 应用 URL ``` --- ## 10. 文档维护 - **审核周期**: 每季度审核一次 - **更新触发**: 系统架构变更、联系人变更、演练发现问题 - **关联文档**: - `docs/dr/dr-runbook.md` - 灾备操作手册 - `docs/dr/reports/` - 演练报告存档 - `scripts/` - 灾备相关脚本 --- ## 11. 变更记录 | 日期 | 版本 | 变更内容 | 变更人 | |------|------|---------|--------| | 2026-06-17 | 1.0 | 初始版本 | - |