Files
NextEdu/docs/dr/dr-plan.md
SpecialX 6585e10c6f feat(P2): 实现质量保障类5项功能(无障碍/视觉回归/通知渠道/漏洞扫描/灾备)
## 新增功能

### 1. 屏幕阅读器兼容性增强(a11y)
- 无障碍工具库:src/shared/lib/a11y.ts
- aria-live Hook:src/shared/hooks/use-aria-live.ts
- a11y 组件:skip-link/visually-hidden/focus-trap/aria-status
- 增强 UI:table.tsx 系统性 ARIA role,dialog.tsx aria-modal
- 审计文档:docs/accessibility/a11y-audit.md(WCAG 2.1 AA 清单)

### 2. 视觉回归测试
- 测试套件:tests/visual/(homepage + 3 个 dashboard)
- 3 视口(desktop/tablet/mobile)× 2 主题(light/dark)
- 动态元素遮罩,避免误报
- playwright.config.ts 新增 visual-chromium 项目
- 文档:docs/testing/visual-regression.md

### 3. 短信/微信推送渠道集成
- 新模块:src/modules/notifications/
- 4 个渠道:SMS(阿里云/腾讯云)、WeChat(公众号)、Email(SMTP)、In-App
- 分发器按用户偏好并行多渠道发送
- 外部 SDK 动态 import,Mock 模式开发可用
- 文档:docs/notifications/channels.md

### 4. 漏洞扫描 CI 集成
- CI security-scan job:npm audit + Snyk + Trivy FS + OWASP ZAP
- 独立工作流 security.yml:每周一深度扫描 + 容器镜像扫描
- 配置:suppressions.json + .trivyignore
- 本地脚本:security-scan.sh/ps1
- 文档:docs/security/scanning.md(SLA 分级)

### 5. 灾备方案
- 脚本:backup-verify/backup-offsite-sync/dr-drill/failover/health-check
- CI 增强:备份后校验+异地同步,每周灾备演练
- 独立工作流 dr-drill.yml:每周一凌晨 4 点自动演练
- 文档:docs/dr/dr-plan.md(RTO 4h/RPO 24h)+ dr-runbook.md(6 故障场景)

## 验证
- npx tsc --noEmit:0 错误
- npm run lint:0 错误 0 警告
2026-06-17 20:18:29 +08:00

9.5 KiB

灾备计划 (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 脚本:

# 手动模式(交互式确认)
./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 版本(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 从备份恢复数据库

# 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. 恢复数据库

    ./scripts/restore-db.sh backups/db_backup_YYYYMMDD_HHMMSS.sql.gz
    
  3. 重启应用

    docker restart nextjs-app
    # 或
    docker stop nextjs-app && docker rm nextjs-app
    # 重新部署
    
  4. 验证数据完整性

    # 运行健康检查
    ./scripts/health-check.sh
    
    # 运行灾备演练(对比数据)
    ./scripts/dr-drill.sh --no-cleanup
    
  5. 恢复流量

    • 验证应用功能正常
    • 逐步恢复用户流量
    • 监控系统指标

8. 监控与告警

8.1 健康检查

# 手动运行健康检查
./scripts/health-check.sh

# 输出 JSON 格式报告
./scripts/health-check.sh > health-report.json

检查项:

  • 应用 HTTP 健康端点
  • 数据库连接
  • 磁盘空间(阈值 90%)
  • 备份新鲜度(24 小时内)

8.2 告警条件

条件 严重级别 通知方式
应用不可达 严重 电话 + 邮件
数据库连接失败 严重 电话 + 邮件
磁盘空间 > 90% 警告 邮件
备份超过 24 小时 警告 邮件
备份校验失败 严重 电话 + 邮件
灾备演练失败 警告 邮件

9. 环境变量配置

# 灾备配置
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 初始版本 -