Skip to content
清晨的一缕阳光
返回

Redis RDB 持久化详解

Redis RDB 持久化详解

RDB(Redis Database Backup)是 Redis 的快照式持久化机制,通过定期保存数据快照实现数据持久化。本文将深入 RDB 的原理、配置和优化。

一、RDB 基础概念

1.1 什么是 RDB

RDB 是时间点快照

数据状态               RDB 文件
┌─────────┐          ┌─────────────┐
│ Key-Value│  快照   │  dump.rdb   │
│ Memory   │ ──────▶ │  (二进制)   │
└─────────┘          └─────────────┘

1.2 RDB 文件结构

RDB 文件格式:
┌─────────────────┐
│ REDIS0009       │  ← 魔数 + 版本
├─────────────────┤
│ 数据库选择      │
├─────────────────┤
│ 键值对 1        │
├─────────────────┤
│ 键值对 2        │
├─────────────────┤
│ ...             │
├─────────────────┤
│ EOF             │  ← 结束标记
├─────────────────┤
│ CRC64 校验和    │  ← 完整性校验
└─────────────────┘

二、触发方式

2.1 自动触发

配置触发条件

# redis.conf
save 900 1        # 900 秒内至少 1 个键变化
save 300 10       # 300 秒内至少 10 个键变化
save 60 10000     # 60 秒内至少 10000 个键变化

触发流程

满足 save 条件

BGSAVE 命令

fork 子进程

子进程写 RDB 文件

父进程继续服务

2.2 手动触发

# 阻塞保存(不推荐生产)
SAVE

# 后台保存(推荐)
BGSAVE

# 检查保存状态
LASTSAVE

# 停止 BGSAVE
BGSAVE ABORT

2.3 关闭 RDB

# 禁用 RDB
save ""

# 或注释所有 save 配置
# save 900 1
# save 300 10
# save 60 10000

三、工作原理

3.1 fork 子进程

// BGSAVE 实现
void bgsaveCommand(client *c) {
    // 1. 检查是否已有 BGSAVE 在运行
    if (server.child_type == CHILD_TYPE_RDB) {
        addReplyError(c, "BGSAVE already in progress");
        return;
    }
    
    // 2. fork 子进程
    pid_t childpid = fork();
    
    if (childpid == 0) {
        // 子进程:执行 RDB 保存
        rdbSaveBackground();
    } else {
        // 父进程:继续服务
        server.rdb_child_pid = childpid;
    }
}

3.2 写时复制(Copy-on-Write)

fork 后:
父进程                    子进程
  │                        │
  │ 继续处理写请求          │
  │                        │
  │ 写页 P                 │
  │                        │
  ├─ 触发 COW              │
  │ 复制页 P               │
  │                        │
  │ 写入新页 P'            │ 读取旧页 P(快照)
  │                        │

优势

3.3 保存流程

1. 创建临时文件 temp-7832.rdb
2. 遍历所有数据库
3. 序列化键值对
4. 写入临时文件
5. 重命名为 dump.rdb
6. 通知父进程完成

四、配置详解

4.1 基本配置

# RDB 文件名
dbfilename dump.rdb

# 工作目录
dir /var/lib/redis

# 压缩
rdbcompression yes

# 校验和
rdbchecksum yes

4.2 触发条件

# 保存条件(满足任一即触发)
save 900 1        # 15 分钟内至少 1 个键变化
save 300 10       # 5 分钟内至少 10 个键变化
save 60 10000     # 1 分钟内至少 1 万个键变化

# 建议配置(根据业务调整)
save 300 100      # 5 分钟 100 个变化
save 60 1000      # 1 分钟 1000 个变化

4.3 停止保存

# 写入失败时继续服务
stop-writes-on-bgsave-error no

# 默认配置(推荐)
stop-writes-on-bgsave-error yes

五、数据恢复

5.1 启动恢复

Redis 启动

检查 dump.rdb 存在

加载 RDB 文件

恢复数据到内存

启动完成

5.2 手动恢复

# 1. 停止 Redis
redis-cli SHUTDOWN

# 2. 备份当前 RDB
cp /var/lib/redis/dump.rdb /var/lib/redis/dump.rdb.bak

# 3. 替换 RDB 文件
cp backup/dump.rdb /var/lib/redis/

# 4. 启动 Redis
redis-server /etc/redis/redis.conf

5.3 恢复验证

# 检查 RDB 文件
redis-check-rdb /var/lib/redis/dump.rdb

# 输出示例
[offset 0] Checking RDB file /var/lib/redis/dump.rdb
[offset 10] AUX FIELD 'redis-ver' = '7.0.0'
[offset 20] AUX FIELD 'aof-preamble' = '0'
...
RDB file is OK

六、性能优化

6.1 fork 优化

问题

fork 时可能阻塞
大数据集 fork 耗时

解决

# 控制最大内存
maxmemory 4gb

# 避免大 Key
# 单个 Key < 10KB

6.2 磁盘优化

# 使用 SSD
dir /mnt/ssd/redis

# 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# 调整 swappiness
sysctl vm.swappiness=1

6.3 配置建议

# 生产环境推荐
save 300 100
save 60 1000

rdbcompression yes
rdbchecksum yes

stop-writes-on-bgsave-error yes

dir /var/lib/redis
dbfilename dump.rdb

七、监控与维护

7.1 监控指标

# 查看 RDB 状态
INFO persistence

# 输出示例
# Persistence
# loading:0
# current_cow_size:0
# last_save_time:1640000000
# last_bgsave_status:ok
# rdb_changes_since_last_save:100

7.2 定期备份

#!/bin/bash
# backup.sh

REDIS_CLI="redis-cli"
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)

# 触发 BGSAVE
$REDIS_CLI BGSAVE

# 等待完成
while [ "$($REDIS_CLI LASTSAVE)" == "$LAST_SAVE" ]; do
    sleep 1
done

# 备份 RDB 文件
cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb

# 压缩
gzip $BACKUP_DIR/dump_$DATE.rdb

# 清理 7 天前备份
find $BACKUP_DIR -name "dump_*.rdb.gz" -mtime +7 -delete

7.3 故障处理

问题 1: BGSAVE 失败

# 检查磁盘空间
df -h

# 检查权限
ls -la /var/lib/redis/

# 查看日志
tail -f /var/log/redis/redis.log

问题 2: RDB 文件损坏

# 检查文件
redis-check-rdb /var/lib/redis/dump.rdb

# 从备份恢复
cp /backup/redis/dump_20240101.rdb /var/lib/redis/dump.rdb

八、最佳实践

8.1 配置策略

场景配置
高可用save 60 1000 + AOF
缓存禁用 RDB
备份save 300 100 + 定期备份
开发save 60 1

8.2 备份策略

每小时:本地备份
每天:异地备份
每周:归档备份

8.3 恢复演练

每月进行一次恢复演练:
1. 从备份恢复
2. 验证数据完整性
3. 记录恢复时间
4. 优化恢复流程

九、常见问题

Q1: RDB vs AOF?

RDB:
- 紧凑,适合备份
- 恢复快
- 可能丢失数据

AOF:
- 数据更安全
- 文件较大
- 恢复慢

建议:同时开启

Q2: fork 失败怎么办?

# 检查内存
free -h

# 检查系统配置
cat /proc/sys/vm/overcommit_memory

# 设置为 1(允许过度分配)
echo 1 > /proc/sys/vm/overcommit_memory

Q3: RDB 文件过大?

# 1. 检查大 Key
redis-cli --bigkeys

# 2. 启用压缩
rdbcompression yes

# 3. 定期清理过期数据

Q4: 如何迁移 RDB 文件?

# 1. 源服务器
BGSAVE

# 2. 复制文件
scp /var/lib/redis/dump.rdb target:/var/lib/redis/

# 3. 目标服务器
redis-cli SHUTDOWN
mv /var/lib/redis/dump.rdb /var/lib/redis/dump.rdb.bak
mv /var/lib/redis/dump.rdb.new /var/lib/redis/dump.rdb
redis-server

总结

Redis RDB 核心要点:

特性说明
格式二进制快照
触发save 配置、BGSAVE
优势紧凑、恢复快
劣势可能丢失数据
适用备份、冷恢复

最佳实践

  1. 合理配置 save 条件
  2. 启用压缩和校验
  3. 定期备份到异地
  4. 监控 BGSAVE 状态
  5. 定期恢复演练

掌握 RDB,保障 Redis 数据安全!

参考资料


分享这篇文章到:

上一篇文章
RAG 评估与监控体系构建
下一篇文章
RAG 重排序与后处理实战