Appearance
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
| 维度 | RDB | AOF |
|---|---|---|
| 文件大小 | 小(压缩的二进制) | 大(文本协议) |
| 恢复速度 | 快(直接加载) | 慢(重放命令) |
| 数据安全 | 可能丢几分钟数据 | 最多丢 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 缓冲区和重写缓冲区。子进程重写完成后,父进程将重写缓冲区的命令追加到新文件,最后原子替换。整个过程不丢失任何命令。
