Skip to content

Redis 持久化详解

  Redis 是内存数据库,数据在内存中。一旦宕机,内存数据全部丢失。持久化就是将内存数据写入磁盘,保证重启后可恢复。Redis 提供 RDB、AOF 和混合持久化三种方案。

一、RDB(Redis DataBase)

1.1 原理

  RDB 是快照持久化,在某个时间点将内存中的所有数据以二进制格式写入磁盘。

RDB 工作原理:

时间线:
  ──────────────────────────────────────────────────────────────
  │ 正常执行命令  │  fork 子进程  │  子进程写 RDB  │  主进程继续  │
  │              │  保存快照     │                │  服务       │
  ──────────────────────────────────────────────────────────────

  1. Redis 调用 fork() 创建子进程
  2. 子进程将当前内存数据写入临时 RDB 文件
  3. 写入完成后,原子替换旧的 RDB 文件
  4. 主进程继续处理请求,不受影响(Copy-on-Write 机制)

1.2 触发方式

bash
# 手动触发
SAVE        # 主进程阻塞,生产不要用
BGSAVE      # 后台 fork 子进程,推荐

# 自动触发(redis.conf)
save 900 1      # 900 秒内至少 1 次修改
save 300 10     # 300 秒内至少 10 次修改
save 60 10000   # 60 秒内至少 10000 次修改

1.3 配置

conf
# redis.conf
dbfilename dump.rdb           # RDB 文件名
dir /data/redis               # 存储目录
save 900 1                    # 自动触发条件
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes   # 写入失败时停止接受写请求
rdbcompression yes            # 启用 LZF 压缩
rdbchecksum yes               # 启用 CRC64 校验

1.4 COW(Copy-on-Write)机制

fork 子进程时,父子进程共享同一块内存:

  ┌────────────────────────────────┐
  │  父进程(主进程)                │
  │  ┌──────────────────────────┐  │
  │  │ 共享内存页(只读)         │  │
  │  └──────────────────────────┘  │
  └────────────────────────────────┘
         │ fork()          

  ┌────────────────────────────────┐
  │  子进程(写 RDB)               │
  │  ┌──────────────────────────┐  │
  │  │ 共享内存页(只读)         │  │
  │  └──────────────────────────┘  │
  └────────────────────────────────┘

  当父进程需要修改数据时:
  1. 操作系统复制该内存页
  2. 父进程在新页上修改
  3. 子进程继续读旧页(不受影响)
  
  ★ 只有被修改的页才会复制,不是全部复制
  ★ 这就是 COW —— 写时复制

二、AOF(Append Only File)

2.1 原理

  AOF 是日志持久化,记录每次写命令,重启时重放命令恢复数据。

AOF 工作原理:

  ┌──────────────────────────────────────────────────────────────────┐
  │  客户端 → SET key value                                          │
  │     │                                                            │
  │     ▼                                                            │
  │  执行命令(修改内存)                                              │
  │     │                                                            │
  │     ▼                                                            │
  │  追加命令到 AOF 缓冲区                                            │
  │     │                                                            │
  │     ▼                                                            │
  │  返回客户端                                                       │
  │     │                                                            │
  │     ▼                                                            │
  │  根据 fsync 策略,将缓冲区刷入磁盘                                  │
  └──────────────────────────────────────────────────────────────────┘

2.2 配置

conf
# redis.conf
appendonly yes                  # 开启 AOF
appendfilename "appendonly.aof" # AOF 文件名

# fsync 策略(核心配置)
appendfsync always    # 每条命令都 fsync,最安全但最慢
appendfsync everysec  # 每秒 fsync 一次,推荐(最多丢 1 秒数据)
appendfsync no        # 由操作系统决定,最快但最不安全

# AOF 重写
auto-aof-rewrite-percentage 100   # 比上次重写增长 100% 时触发
auto-aof-rewrite-min-size 64mb    # 最小 64MB 才触发

2.3 AOF 重写(Rewrite)

  AOF 文件会越来越大,重写是将多条命令合并为一条,减小文件体积。

重写前(appendonly.aof):
  SET count 1
  SET count 2
  SET count 3
  SET count 4
  SET count 5
  (5 条命令,文件不断增长)

重写后(appendonly.aof):
  SET count 5
  (1 条命令,小很多)

重写原理:
  1. fork 子进程
  2. 子进程读取当前内存数据,生成最小命令集
  3. 写入新 AOF 文件
  4. 重写期间的新命令写入 AOF 重写缓冲区
  5. 子进程完成后,将重写缓冲区的命令追加到新文件
  6. 原子替换旧 AOF 文件

2.4 AOF 文件修复

bash
# 如果 AOF 文件损坏
redis-check-aof --fix appendonly.aof

三、RDB vs AOF

维度RDBAOF
文件大小小(压缩的二进制)大(文本协议)
恢复速度快(直接加载)慢(重放命令)
数据安全可能丢几分钟数据最多丢 1 秒(everysec)
磁盘 IO低(批量写入)高(频繁写入)
重写机制自动 fork 子进程自动 fork 子进程
适用场景备份、灾难恢复数据安全要求高
RDB 优点:
  ✅ 文件紧凑,适合备份和灾难恢复
  ✅ 恢复大数据集比 AOF 快
  ✅ 对性能影响小(fork 子进程)

RDB 缺点:
  ❌ 两次快照之间宕机,会丢失数据
  ❌ fork 子进程时,如果数据量大,可能阻塞主进程

AOF 优点:
  ✅ 数据更安全(everysec 最多丢 1 秒)
  ✅ 文件可读,可手动修改
  ✅ 自动重写,文件不会无限增长

AOF 缺点:
  ✅ 文件更大,恢复更慢
  ✅ 对性能影响稍大(写磁盘频率高)

四、如何选择

场景分析:

1. 只做缓存,数据可丢失
   → 都不需要,关闭持久化

2. 数据重要,可接受几分钟丢失
   → 只用 RDB,save 60 10000

3. 数据非常重要,不能丢
   → 只用 AOF,appendfsync everysec

4. 数据重要 + 备份需求
   → RDB + AOF 同时开启(Redis 4.0 前)
   → 混合持久化(Redis 4.0+ 推荐)

5. 性能敏感,数据可少量丢失
   → RDB 低频保存

五、Redis 4.0 混合持久化

5.1 原理

混合持久化文件结构:

  ┌────────────────────────────────────────────────┐
  │           RDB 格式(前半部分)                    │
  │  当前内存快照,二进制格式,快速加载               │
  ├────────────────────────────────────────────────┤
  │           AOF 格式(后半部分)                    │
  │  RDB 快照之后的增量命令,日志格式,保证不丢       │
  └────────────────────────────────────────────────┘
  
  优点:RDB 的快 + AOF 的数据安全,取两者之长

5.2 配置

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

六、数据恢复流程

Redis 重启 → 恢复数据

  ┌──────────────────────────────────────────────────────┐
  │                                                      │
  │  AOF 开启?                                           │
  │    │                                                  │
  │    ├── 是 → 加载 AOF 文件(优先)                       │
  │    │       ├── 混合持久化格式?                        │
  │    │       │   ├── 是 → 加载 RDB 部分 + 重放 AOF 部分  │
  │    │       │   └── 否 → 重放全部 AOF 命令              │
  │    │       └── 恢复成功                                │
  │    │                                                  │
  │    └── 否 → 加载 RDB 文件                             │
  │            └── 恢复成功                                │
  └──────────────────────────────────────────────────────┘

七、面试要点

Q1:RDB 和 AOF 各自有什么优缺点?

  RDB:文件小恢复快,但可能丢几分钟数据。AOF:数据安全(最多丢 1 秒),但文件大恢复慢。RDB 适合备份,AOF 保证数据安全。

Q2:RDB 和 AOF 如何选择?

  Redis 4.0+ 推荐混合持久化(aof-use-rdb-preamble yes),既有 RDB 的快速恢复,又有 AOF 的数据安全。如果版本低于 4.0,同时开启 RDB + AOF。

Q3:Redis 4.0 混合持久化是什么?

  AOF 文件前半部分用 RDB 格式(快照),后半部分用 AOF 格式(增量命令)。重启时先加载 RDB 快照快速恢复,再重放增量命令保证完整性。兼顾了速度和安全性。

Q4:AOF 重写过程中有新的写命令怎么办?

  AOF 重写使用 AOF 重写缓冲区。重写期间的新命令同时写入旧的 AOF 缓冲区和重写缓冲区。子进程重写完成后,父进程将重写缓冲区的命令追加到新文件,最后原子替换。整个过程不丢失任何命令。