Redis 持久化机制: RDB vs AOF

深入 Redis 持久化原理:RDB 快照(BGSAVE、Copy-On-Write)、AOF 日志(重写机制、 durability 级别)、混合持久化,以及生产环境选型与灾难恢复策略。

1. 为什么需要持久化

Redis 是内存数据库,进程退出后数据全部丢失。持久化将内存数据保存到磁盘,用于数据备份、灾难恢复和进程重启后的数据恢复。


2. RDB(Redis Database)快照

2.1 触发方式

# 手动触发
SAVE            # 同步保存,阻塞主线程(生产不用)
BGSAVE          # 后台异步保存,fork 子进程

# 自动触发(redis.conf)
save 900 1      # 900 秒内至少 1 个 key 变化 → 触发 BGSAVE
save 300 10     # 300 秒内至少 10 个 key 变化
save 60 10000   # 60 秒内至少 10000 个 key 变化
save ""         # 禁用 RDB

2.2 Copy-On-Write 原理

BGSAVE 执行时:

1. 主进程 fork() 子进程
   │
   ├── 父进程(Redis 主线程)──→ 处理客户端请求
   │                               │
   │   写入 key A ──→ 页面被修改 ──→ COW 复制页面
   │   │                              │
   │   新数据 ──→ 新页                旧页(子进程读取)
   │
   └── 子进程 ──→ 读取内存页 ──→ 写入 RDB 文件

COW 开销:fork 时只需复制页表,无需复制全部内存
           实际额外内存 ≈ 写入操作涉及的数据量

2.3 RDB 优缺点

优点缺点
文件紧凑,备份和传输方便可能丢失两次快照间的数据
恢复速度快(直接加载)大数据量时 fork 可能耗时较长
对运行时性能影响小

3. AOF(Append Only File)

3.1 写入策略

# 同步策略
appendfsync always      # 每条命令 fsync → 最安全,性能最差
appendfsync everysec    # 每秒 fsync → 默认,最多丢 1 秒数据
appendfsync no          # 由 OS 决定 → 最快,最不安全

# 在 rewrite 期间是否不 fsync(减少 IO 压力)
no-appendfsync-on-rewrite yes

3.2 AOF 重写(Rewrite)

AOF 持续追加会不断膨胀,重写将内存中的最新数据生成精简的命令集。

BGREWRITEAOF    # 手动触发重写

# 自动重写条件
auto-aof-rewrite-percentage 100   # AOF 增长超过上次重写后 100%
auto-aof-rewrite-min-size 64mb    # 最小 64MB 才重写
重写流程:

1. fork 子进程,扫描内存生成新 AOF 文件
2. 父进程在此期间的新写入写入「AOF 重写缓冲区」
3. 子进程完成后,父进程将重写缓冲区的命令追加到新 AOF
4. 原子替换旧 AOF 文件

4. 混合持久化(Redis 4.0+)

aof-use-rdb-preamble yes    # 默认开启
重写后的 AOF 文件格式:

┌─────────────────────────────────────────┐
│  RDB 格式头部(二进制)                    │  ← 全量数据快照
│  快速加载整个数据集                        │
├─────────────────────────────────────────┤
│  AOF 格式命令(文本)                      │  ← 重写后的增量命令
│  保证重写期间的数据不丢失                   │
└─────────────────────────────────────────┘

恢复时:
  1. 读取 RDB 部分 → 快速加载全量数据
  2. 执行 AOF 部分的命令 → 补齐增量数据

5. 选型与生产建议

场景推荐原因
纯缓存(可重建)RDB + 禁用 AOF内存为王,重启后重建
允许分钟级丢失RDB only简单、恢复快
不能丢数据AOF everysec最多丢 1 秒
生产推荐RDB + AOF 混合兼顾恢复速度和数据安全
# 生产配置示例
save 900 1
save 300 10
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 128mb


6. 持久化恢复流程

Redis 启动时的数据恢复:

1. 检查 AOF 是否开启且存在
   ├── AOF 存在 ──→ 加载 AOF(如果开启了混合持久化,先读 RDB 头部再读 AOF)
   │                   └── 校验 AOF 格式,如果损坏尝试用备份恢复
   │                   └── 如果备份也损坏,可以删除 AOF 直接用 RDB(会丢失部分数据)
   │
   └── AOF 不存在 ──→ 检查 RDB 是否存在
                       ├── RDB 存在 ──→ 加载 RDB
                       │                   └── RDB 加载速度快(二进制格式)
                       │
                       └── RDB 不存在 ──→ 空实例启动

恢复性能

数据量RDB 加载AOF 加载 (rewrite 后)
1GB2-5s5-10s
10GB20-60s60-120s
50GB2-5min5-10min

7. 持久化对性能的影响

配置CPU 影响内存影响适用场景
AOF always高(每次写入都 fsync)低金融级,不能丢数据
AOF everysec(默认)低低大部分生产环境
AOF no最低低可接受丢失部分数据
RDBBKSAVE 时 fork 有短暂影响fork 时 COW 增加定时备份

fork 阻塞时间

# 查看最近一次 fork 耗时(微秒)
redis-cli INFO | grep latest_fork_usec

# 如果 fork 耗时较长(> 100ms),考虑:
# 1. 使用更大的 Redis 实例内存
# 2. 在 slaves 上执行 BGSAVE
# 3. 升级 Linux 内核以优化 fork 性能

8. 持久化监控指标

指标命令健康阈值
RDB 最后保存时间INFO Persistence → rdb_last_bgsave_status状态为 ok
AOF 最后写入状态INFO Persistence → aof_last_bgrewrite_status状态为 ok
AOF 缓冲区大小INFO Persistence → aof_buffer_length< 32MB
当前 AOF 大小INFO Persistence → aof_current_size关注增长率

延伸阅读

总结

Redis 持久化的核心在于平衡数据安全与性能。RDB 提供紧凑的快照备份和快速恢复能力,适合灾难恢复场景;AOF 通过追加日志实现更高的数据安全性,默认每秒 fsync 的策略在多数生产环境中是最佳折中。Redis 4.0 引入的混合持久化结合了两者的优势,成为当前生产环境的首选方案。运维中需要关注 fork 操作对内存和延迟的影响,合理配置自动触发条件,并建立完善的备份与恢复流程。对于不能容忍数据丢失的核心业务,建议同时使用 RDB + AOF 混合持久化,配合主从复制实现多重数据保护。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「redis」更多文章

  1. 多租户隔离与资源配额:共享 Redis 的边界设计
  2. Key 设计与命名规范:Redis 里唯一的结构约束
  3. 代理与路由方案:客户端直连之外的另一种选择