一、为什么数据备份至关重要
数据是企业的核心资产,数据丢失可能造成不可挽回的损失:
- 人为失误:误删除、误修改
- 系统故障:硬盘损坏、数据库崩溃
- 安全威胁:勒索病毒、黑客攻击
- 自然灾害:火灾、洪水、地震
- 合规要求:法规对数据保留的要求
数据备份的核心目标:
- 在任何情况下都能恢复数据
- 恢复时间越短越好
- 恢复的数据越完整越好
二、备份策略分类
1. 按备份范围分类
| 类型 | 说明 | 备份时间 | 数据丢失量 |
|---|---|---|---|
| 全量备份 | 备份所有数据 | 长 | 无 |
| 增量备份 | 备份自上次备份后的增量 | 短 | 取决于频率 |
| 差异备份 | 备份自上次全量后的差异 | 中 | 介于两者之间 |
2. 备份频率规划
每日增量 + 每周全量 + 每月归档
示例:
- 每日凌晨2点执行增量备份
- 每周日凌晨2点执行全量备份
- 每月最后一天执行月度归档备份
3. 备份保留策略
| 备份类型 | 保留周期 | 存储位置 |
|---|---|---|
| 日备份 | 7天 | 本地磁盘 |
| 周备份 | 4周 | 本地磁盘 + 对象存储 |
| 月备份 | 12个月 | 对象存储(异地) |
| 年备份 | 永久 | 冷存储/磁带 |
三、MySQL备份方案
1. 逻辑备份(mysqldump)
全量备份脚本:
bash
#!/bin/bash
# backup_full.sh
BACKUP_DIR="/data/backup/mysql"
DATE=$(date +%Y%m%d)
MYSQL_USER="backup"
MYSQL_PASSWORD="password"
MYSQL_HOST="localhost"
# 创建备份目录
mkdir -p ${BACKUP_DIR}/${DATE}
# 执行全量备份
mysqldump -h${MYSQL_HOST} \
-u${MYSQL_USER} \
-p${MYSQL_PASSWORD} \
--single-transaction \
--routines \
--triggers \
--events \
--all-databases \
| gzip > ${BACKUP_DIR}/${DATE}/full_backup.sql.gz
# 删除7天前的备份
find ${BACKUP_DIR} -mtime +7 -type f -name "*.sql.gz" -delete
echo "全量备份完成: ${DATE}"
增量备份(基于Binlog):
bash
#!/bin/bash
# backup_incr.sh
BACKUP_DIR="/data/backup/mysql/incremental"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_DATA_DIR="/var/lib/mysql"
# 刷新日志,锁定位置
mysql -e "FLUSH LOGS;"
# 获取当前的binlog文件
BINLOG_FILE=$(mysql -e "SHOW MASTER STATUS\G" | grep File | awk '{print $2}')
# 复制binlog文件到备份目录
mkdir -p ${BACKUP_DIR}/${DATE}
cp ${MYSQL_DATA_DIR}/${BINLOG_FILE} ${BACKUP_DIR}/${DATE}/
# 记录当前的binlog位置
echo ${BINLOG_FILE} > ${BACKUP_DIR}/last_binlog
echo "增量备份完成: ${DATE}"
2. 物理备份(XtraBackup)
全量备份:
bash
#!/bin/bash
# xtrabackup_full.sh
BACKUP_DIR="/data/backup/xtrabackup"
DATE=$(date +%Y%m%d)
TARGET_DIR="${BACKUP_DIR}/${DATE}"
# 执行备份
xtrabackup \
--backup \
--target-dir=${TARGET_DIR} \
--user=backup \
--password=password \
--host=localhost
# 准备备份(应用日志)
xtrabackup \
--prepare \
--target-dir=${TARGET_DIR}
# 压缩备份
tar -czf ${TARGET_DIR}.tar.gz -C ${BACKUP_DIR} ${DATE}
rm -rf ${TARGET_DIR}
echo "XtraBackup全量备份完成: ${DATE}"
3. MySQL备份恢复
全量恢复:
bash
# 停止MySQL
systemctl stop mysql
# 清空数据目录
rm -rf /var/lib/mysql/*
# 解压备份
gunzip full_backup.sql.gz
# 恢复数据
mysql -u root -p < full_backup.sql
# 启动MySQL
systemctl start mysql
四、Redis备份方案
1. RDB快照备份
配置自动备份:
conf
# redis.conf
save 900 1 # 900秒内至少1次修改则触发BGSAVE
save 300 10 # 300秒内至少10次修改则触发BGSAVE
save 60 10000 # 60秒内至少10000次修改则触发BGSAVE
# 备份文件位置
dir /data/redis/backup
# RDB压缩
rdbcompression yes
手动备份脚本:
bash
#!/bin/bash
# redis_backup.sh
BACKUP_DIR="/data/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)
# BGSAVE异步执行备份
redis-cli BGSAVE
# 等待备份完成
while [ $(redis-cli LASTSAVE) == $(redis-cli LASTSAVE) ]; do
sleep 1
done
# 复制备份文件
cp /data/redis/dump.rdb ${BACKUP_DIR}/dump_${DATE}.rdb
# 压缩备份
gzip ${BACKUP_DIR}/dump_${DATE}.rdb
echo "Redis备份完成: ${DATE}"
2. AOF持久化备份
conf
# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
dir /data/redis/backup
五、文件备份方案
1. 对象存储备份
Java代码实现:
java
@Service
public class FileBackupService {
@Autowired
private OSS ossClient;
@Value("${oss.bucket-name}")
private String bucketName;
public void backupFile(String localPath, String backupDate) {
File file = new File(localPath);
if (!file.exists()) {
throw new RuntimeException("备份文件不存在: " + localPath);
}
// 构建OSS路径
String objectKey = String.format("backup/%s/%s",
backupDate, file.getName());
// 上传到OSS
ossClient.putObject(bucketName, objectKey, file);
log.info("文件备份成功: {} -> oss://{}/{}",
localPath, bucketName, objectKey);
}
}
2. Rsync增量备份
bash
#!/bin/bash
# rsync_backup.sh
SOURCE_DIR="/data/app"
BACKUP_DIR="/data/backup/app"
RSYNC_USER="backup"
RSYNC_HOST="backup-server"
# 使用rsync进行增量备份
rsync -avz \
--delete \
--bwlimit=5000 \
${SOURCE_DIR}/ \
${RSYNC_USER}@${RSYNC_HOST}::backup/${HOSTNAME}/
echo "Rsync备份完成"
六、备份策略设计
1. 3-2-1备份原则
- 3份数据副本:生产数据 + 本地备份 + 异地备份
- 2种存储介质:磁盘 + 对象存储/磁带
- 1份离线副本:冷存储/异地,防范勒索病毒
2. 分层备份架构
生产环境
↓
本地备份(分钟级RPO)
↓
同城备份(小时级RPO)
↓
异地备份(天级RPO)
3. 备份监控
java
@Component
public class BackupMonitor {
@Scheduled(cron = "0 0 3 * * ?")
public void checkBackupStatus() {
// 检查备份任务是否成功执行
LocalDate today = LocalDate.now();
List<BackupJob> jobs = backupJobRepository.findByDate(today);
for (BackupJob job : jobs) {
if (!"SUCCESS".equals(job.getStatus())) {
alertService.alert("备份失败: " + job.getJobName());
}
}
// 检查备份存储空间
long usedSpace = backupStorageService.getUsedSpace();
long totalSpace = backupStorageService.getTotalSpace();
double usageRatio = (double) usedSpace / totalSpace;
if (usageRatio > 0.8) {
alertService.alert("备份存储空间使用率超过80%");
}
}
}
七、灾难恢复演练
1. 演练计划
| 演练类型 | 频率 | 覆盖范围 |
|---|---|---|
| 单表恢复 | 每月 | 测试环境 |
| 全量恢复 | 每季度 | 隔离环境 |
| 灾难切换 | 每半年 | 生产模拟 |
| 跨机房切换 | 每年 | 全链路 |
2. 演练验收清单
- 备份文件完整,无损坏
- 恢复脚本执行无报错
- 数据恢复后完整性验证通过
- 应用启动正常
- 核心业务流程验证通过
- 监控告警正常触发
- 恢复时间在预期范围内
八、总结
数据备份是数据安全的最后一道防线:
- 策略设计:3-2-1原则 + 分层备份
- 工具选择:mysqldump/XtraBackup + Redis备份 + 对象存储
- 自动化:备份任务自动化执行
- 监控告警:备份状态实时监控
- 定期演练:确保备份可恢复
备份不是目的,恢复才是。 定期演练是检验备份有效性的唯一标准。
个人观点,仅供参考