19.9.3 备份一致性与应用停机窗口管理

备份一致性与应用停机窗口管理的目标是:在可控的业务影响下获得可恢复且一致的备份点。实践中需明确一致性级别(强一致/最终一致/会话一致)与“数据面依赖顺序”(数据库→缓存→消息队列→配置中心→对象存储),并记录时间点与位点,避免跨组件时间点不一致。

文章图片

一致性实现分为应用层与存储层:
- 应用层:只读模式、停写、冻结事务、流量切换(写流量切走)。
- 存储层:文件系统/存储阵列快照、数据库原生备份机制。

示例:MySQL 一致性备份(XtraBackup)
1) 安装与准备(Debian/Ubuntu):

# 安装 Percona XtraBackup(示例)
sudo apt-get update
sudo apt-get install -y percona-xtrabackup-80

# 确认版本
xtrabackup --version

2) 建立短只读窗口并记录位点:

# 进入 MySQL
mysql -uroot -p -e "SHOW MASTER STATUS\G"

# 推荐使用备份锁(MySQL 8.0)
mysql -uroot -p -e "LOCK INSTANCE FOR BACKUP;"
# 说明:锁住DDL/备份相关操作,不阻塞读取

3) 执行热备并记录位点:

# 备份目录
sudo mkdir -p /data/backup/mysql/full_$(date +%F)
# 执行备份
sudo xtrabackup --backup \
  --target-dir=/data/backup/mysql/full_$(date +%F) \
  --user=backup --password='***'

# 释放备份锁
mysql -uroot -p -e "UNLOCK INSTANCE;"

# 查看备份元数据(含 binlog 位点)
cat /data/backup/mysql/full_$(date +%F)/xtrabackup_binlog_info

预期效果:xtrabackup_binlog_info 输出 binlog.000xxx 1234567,表示一致性位点。

4) 备份校验与抽样恢复:

# 生成校验和
cd /data/backup/mysql/full_$(date +%F)
find . -type f -print0 | xargs -0 sha256sum > SHA256SUMS

# 抽样恢复到测试实例
sudo systemctl stop mysql
sudo rm -rf /var/lib/mysql/*
sudo xtrabackup --prepare --target-dir=/data/backup/mysql/full_$(date +%F)
sudo xtrabackup --copy-back --target-dir=/data/backup/mysql/full_$(date +%F)
sudo chown -R mysql:mysql /var/lib/mysql
sudo systemctl start mysql

示例:Redis 一致性点(RDB/AOF)

# 进入只读窗口(应用层切写)
# 触发 RDB 快照
redis-cli BGSAVE
# 查看状态
redis-cli info persistence | egrep "rdb_bgsave_in_progress|rdb_last_save_time"

# 如使用 AOF,强制重写减小体积
redis-cli BGREWRITEAOF

# 备份文件
cp /var/lib/redis/dump.rdb /data/backup/redis/dump_$(date +%F).rdb
cp /var/lib/redis/appendonly.aof /data/backup/redis/aof_$(date +%F).aof

预期效果:rdb_bgsave_in_progress:0rdb_last_save_time 更新。

示例:Kafka 一致性点(停写+offset记录)

# 暂停生产者(应用层停写/流控)
# 记录 consumer group 的 offset
kafka-consumer-groups.sh --bootstrap-server kafka01:9092 \
  --describe --group order-service \
  > /data/backup/kafka/order-service.offsets.$(date +%F)

# 备份日志目录(示例,需保证停写)
rsync -a /var/lib/kafka/logs/ /data/backup/kafka/logs_$(date +%F)/

预期效果:offset 记录文件可用于恢复点对齐。

停机窗口管理流程示例(脚本化)

#!/usr/bin/env bash
# /usr/local/bin/backup_window.sh
# 1) 写流量切走 2) 应用只读 3) 执行备份 4) 恢复写入

set -e

echo "[1/4] 切写流量到只读节点"
# 示例:标记上游为只读(具体依赖 LB/服务治理)
curl -X POST http://gateway/api/traffic/switch?mode=read-only

echo "[2/4] 应用进入维护模式"
curl -X POST http://app/api/maintenance/enable

echo "[3/4] 触发数据库备份"
xtrabackup --backup --target-dir=/data/backup/mysql/full_$(date +%F)

echo "[4/4] 恢复应用写入"
curl -X POST http://app/api/maintenance/disable
curl -X POST http://gateway/api/traffic/switch?mode=read-write

echo "done."

预期效果:窗口内写流量被限制,备份完成后恢复读写。

常见排错清单
- 备份阻塞或耗时过长
- 排查:SHOW PROCESSLIST; 查找长事务
- 处理:协调业务缩短事务或提前“只读窗口”
- MySQL 备份失败:xtrabackup: Error: log scan aborted
- 可能原因:磁盘空间不足或权限不足
- 处理:df -h 检查空间;确保备份目录可写
- Redis BGSAVE 失败:MISCONF
- 可能原因:磁盘写入失败或 stop-writes-on-bgsave-error
- 处理:修复磁盘后 CONFIG SET stop-writes-on-bgsave-error no

练习
1) 在测试库中执行一次 MySQL 热备并记录 binlog 位点,随后在新实例恢复并验证数据一致性。
2) 模拟 Kafka 生产者停写 5 分钟,记录 offset 并备份日志目录,验证恢复后消费一致。
3) 编写并运行 backup_window.sh,完成“切写→维护→备份→恢复”的全流程演练,并记录窗口耗时与成功率。