跳到主要内容

Redis 持久化

问题

Redis 有哪些持久化方式?RDB 和 AOF 的区别是什么?如何选择持久化策略?

答案

持久化方式概览

方式原理安全性性能
RDB定时生成内存快照可能丢失最后一次快照后的数据对运行时性能影响小
AOF记录每条写命令最多丢失 1 秒数据写操作有一定开销
混合持久化RDB + AOF 结合兼顾两者优点Redis 4.0+ 推荐

RDB(Redis Database)

RDB 将某个时刻的内存快照以二进制文件的形式保存到磁盘(默认文件名 dump.rdb)。

触发方式

自动触发(redis.conf)
# save <秒数> <修改次数>
save 900 1 # 900 秒内至少 1 次修改
save 300 10 # 300 秒内至少 10 次修改
save 60 10000 # 60 秒内至少 10000 次修改
手动触发
SAVE        # 同步执行,阻塞主进程(生产禁用)
BGSAVE # 后台异步执行,fork 子进程

BGSAVE 执行流程

Copy-On-Write(COW)

fork 后父子进程共享相同的内存页。当主进程修改数据时,操作系统会复制对应的内存页给子进程,子进程仍然写入 fork 时刻的快照。这就是写时复制(COW) 机制。

COW 的风险:如果 fork 后主进程大量写入,需要复制大量页面,可能导致内存翻倍。

RDB 优缺点

优点缺点
文件紧凑,适合备份和传输两次快照之间的数据可能丢失
恢复速度快(直接加载二进制)fork 子进程时大内存实例可能卡顿
对运行时性能影响小数据安全性不如 AOF

AOF(Append Only File)

AOF 将每条写命令追加到日志文件(默认 appendonly.aof),重启时通过重放命令恢复数据。

开启 AOF

redis.conf
appendonly yes
appendfilename "appendonly.aof"

写入流程

三种刷盘策略

策略行为数据安全性能
always每条命令都 fsync最高(不丢数据)最低
everysec(默认)每秒 fsync最多丢 1 秒折中
no由操作系统决定可能丢较多数据最高

AOF 重写

随着写命令不断追加,AOF 文件会越来越大。AOF 重写 根据当前内存数据生成最精简的命令集,替换旧文件。

触发 AOF 重写
BGREWRITEAOF                           # 手动触发

# 自动触发条件(redis.conf)
auto-aof-rewrite-percentage 100 # 文件增长超过上次重写后的 100%
auto-aof-rewrite-min-size 64mb # 最小文件大小

重写过程中新的写命令会同时写入旧 AOF 文件AOF 重写缓冲区,确保重写期间数据不丢失。

AOF 优缺点

优点缺点
数据安全性高(最多丢 1 秒)文件体积比 RDB 大
人类可读(文本格式)恢复速度比 RDB 慢(需重放命令)
支持重写压缩写操作有额外开销

混合持久化(Redis 4.0+)

开启混合持久化
aof-use-rdb-preamble yes               # 默认开启(Redis 5.0+)

AOF 重写时,前半部分以 RDB 格式写入(内存快照),后半部分以 AOF 格式追加(重写期间的增量命令)。

[RDB 二进制数据 | AOF 增量命令]

兼顾了两者的优点:

  • 恢复速度快(RDB 部分直接加载)
  • 数据安全性高(AOF 部分补齐增量)

RDB vs AOF 对比

对比维度RDBAOF
文件格式二进制快照文本命令日志
数据安全可能丢几分钟数据最多丢 1 秒
文件大小小(压缩)大(命令日志)
恢复速度
性能影响fork 时有短暂影响写操作有持续影响
适用场景数据备份、灾难恢复数据安全要求高

持久化策略选择

场景推荐方案
纯缓存,丢失可接受不开持久化,或只开 RDB
数据安全要求高AOF(everysec)+ RDB 定期备份
生产环境推荐混合持久化(RDB + AOF)
主从架构主节点 AOF,从节点 RDB 备份

常见面试问题

Q1: RDB 和 AOF 的区别?

答案

核心区别三点:

  1. 记录内容:RDB 记录内存快照(某个时间点的全量数据),AOF 记录写命令日志(增量操作)
  2. 数据安全:RDB 可能丢失最后一次快照后的数据(几分钟),AOF 最多丢 1 秒(everysec 策略)
  3. 恢复速度:RDB 直接加载二进制快照,速度快;AOF 需要逐条重放命令,速度慢

生产环境推荐使用混合持久化(Redis 4.0+),结合两者优点。

Q2: RDB 的 BGSAVE 如何保证数据一致性?

答案

通过操作系统的 COW(Copy-On-Write,写时复制) 机制:

  1. 主进程 fork() 出子进程,此时父子共享相同的物理内存页
  2. 子进程开始遍历内存生成 RDB 文件,读取的是 fork 时刻的数据
  3. 主进程修改数据时,操作系统为被修改的页面创建副本,子进程仍然访问原始页面
  4. 所以子进程写入的是 fork 时刻的一致性快照

风险:如果 fork 后主进程写入量很大,COW 需要复制大量页面,可能导致内存使用接近翻倍。

Q3: AOF 文件太大怎么办?

答案

通过 AOF 重写(BGREWRITEAOF) 解决。重写过程:

  1. fork 子进程,根据当前内存数据生成最精简的命令集
  2. 例如对同一个 key 的 100 次 SET 操作,重写后只保留最后一次
  3. 重写期间的新命令同时写入旧 AOF 和重写缓冲区
  4. 重写完成后,将重写缓冲区的命令追加到新 AOF 文件,原子替换旧文件

可以设置自动触发条件:文件增长超过上次重写后的 auto-aof-rewrite-percentage(默认 100%)。

Q4: Redis 重启时如何恢复数据?

答案

恢复优先级:

  1. 如果开启了 AOF(appendonly yes),优先加载 AOF 文件(数据更完整)
  2. 如果没有 AOF,则加载 RDB 文件(dump.rdb
  3. 如果使用了混合持久化,AOF 文件前半部分是 RDB 格式(快速加载),后半部分是 AOF 增量命令(补齐数据)

加载过程中如果文件损坏,可以使用 redis-check-aof --fixredis-check-rdb 工具修复。

Q5: 生产环境如何配置持久化?

答案

推荐配置:

# 开启 AOF
appendonly yes
appendfsync everysec

# 开启混合持久化
aof-use-rdb-preamble yes

# RDB 作为补充备份
save 900 1
save 300 10

# 定期将 RDB 备份到异地(crontab)

额外建议:

  • 控制 Redis 内存使用量,避免 fork 时 COW 开销过大
  • 主从架构中,从节点负责 RDB 备份,减少主节点压力
  • 监控 latest_fork_usec(最近一次 fork 耗时),超过 1 秒需要关注

相关链接