Skip to content

RDB vs AOF 对比与混合持久化

面试官:「Redis 持久化用 RDB 还是 AOF?」

你:「都用。」

面试官眉毛一挑:「说说看。」

好,这篇文章帮你把这个问题的答案讲透。

RDB vs AOF 全方位对比

核心原理对比

维度RDBAOF
持久化方式二进制快照追加写命令
文件格式二进制压缩格式文本命令
数据完整性快照时刻的数据可以更实时
恢复速度快(直接加载)慢(重放命令)
文件大小
对性能影响fork 子进程,短暂阻塞持续 I/O 开销

数据安全性对比

假设每分钟写操作数相同:

场景RDBAOF
每 5 分钟快照最多丢失 5 分钟数据-
AOF everysec-最多丢失 1 秒数据
AOF always-数据完全不丢失

结论:AOF 的数据安全性更高。

性能对比

┌─────────────────────────────────────────────────────────────────┐
│                         写操作性能                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   RDB:                                                           │
│   ┌──────┐     ┌──────┐     ┌──────┐     ┌──────┐              │
│   │ 处理 │────▶│ fork │────▶│ 快照 │────▶│ 返回 │              │
│   │ 写入 │     │ 子进程 │     │ 写入 │     │      │              │
│   └──────┘     └──────┘     └──────┘     └──────┘              │
│     ↓           ↓                                          │
│   正常速度    fork 期间短暂阻塞(毫秒~秒级)                       │
│                                                                 │
│   AOF:                                                           │
│   ┌──────┐     ┌──────┐     ┌──────┐                          │
│   │ 处理 │────▶│ 写入 │────▶│ 刷盘 │────▶ 返回                │
│   │ 写入 │     │ 缓冲区 │     │  (根据策略) │                   │
│   └──────┘     └──────┘     └──────┘                          │
│     ↓           ↓                                             │
│   正常速度    缓冲区写入   everysec 模式每秒一次                  │
│                        同步到磁盘                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

资源占用对比

资源RDBAOF
CPUfork + 压缩时较高持续写入,略有影响
内存COW 期间可能翻倍正常
磁盘 I/O快照时集中写入持续追加写入
文件大小紧凑(压缩)膨胀(追加命令)

各自优缺点总结

RDB

优点缺点
文件紧凑,恢复快可能丢失快照间隔的数据
对性能影响小fork 可能耗时(大数据量时)
适合备份和灾难恢复-
适合冷备份-

AOF

优点缺点
数据安全性高文件较大
可配置刷盘策略恢复速度慢
日志格式可读极端情况下可能比 RDB 慢
支持重写压缩-

混合持久化:鱼和熊掌兼得

什么是混合持久化?

Redis 4.0 引入了 混合持久化,结合 RDB 和 AOF 的优点:

┌─────────────────────────────────────────────────────────────────┐
│                       混合 AOF 文件                              │
│                                                                 │
│   [RDB 二进制格式]  │  [AOF 文本格式]                           │
│   (数据快照,快)     │  (增量命令,紧凑)                          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

为什么混合持久化更好?

场景纯 AOF混合持久化
恢复速度慢(重放所有命令)快(RDB 部分直接加载)
文件大小大(全量 AOF 命令)小(RDB 二进制紧凑)
数据安全高(可配置)高(结合两者)

配置混合持久化

bash
# redis.conf

# 开启 AOF
appendonly yes

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

# AOF 写入策略
appendfsync everysec

混合持久化的工作流程

┌─────────────────────────────────────────────────────────────────┐
│                     正常运行时                                   │
│                                                                 │
│   写操作 → AOF 缓冲区 → 刷盘(everysec)                         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

                              │ 触发 AOF 重写

┌─────────────────────────────────────────────────────────────────┐
│                      AOF 重写时                                  │
│                                                                 │
│   fork 子进程                                                     │
│   │                                                              │
│   ├─→ 生成 RDB 格式的完整数据快照                               │
│   │                                                              │
│   └─→ 生成后续的 AOF 增量命令                                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                     重写后的文件                                  │
│                                                                 │
│   [RDB 快照] + [AOF 增量]                                        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

恢复时的加载顺序

Redis 7.0 之前的版本:

1. 检查 AOF 是否存在
2. 如果有 AOF,优先加载 AOF
   - 混合 AOF:先解析 RDB 部分,再追加 AOF 部分
   - 纯 AOF:重放所有命令
3. 如果没有 AOF,加载 RDB

Redis 7.0+(Multi-Part AOF):

1. 读取 manifest 文件
2. 按顺序加载 base 文件(RDB 格式)
3. 依次加载 incr 文件(AOF 格式)
4. 合并恢复数据

最佳实践:如何选择?

场景一:追求极致性能,允许分钟级数据丢失

bash
# 只用 RDB
save 900 1
save 300 10
save 60 10000

appendonly no

场景二:需要高性能又要数据安全

bash
# RDB + AOF 混合(推荐)
save 3600 1

appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes

场景三:金融级数据安全

bash
# 只用 AOF + always
appendonly yes
appendfsync always

# 可以关闭 RDB 自动快照
save ""

场景四:数据量大,恢复要快

bash
# 混合持久化 + 合理的重写配置
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 1gb

生产环境配置模板

bash
# redis.conf - 持久化配置

# ==================== RDB ====================
# 自动快照
save 900 1
save 300 10
save 60 10000

# RDB 文件
dbfilename dump.rdb
dir /var/lib/redis

# RDB 压缩
rdbcompression yes
rdbchecksum yes

# ==================== AOF ====================
# 开启 AOF
appendonly yes
appendfilename "appendonly.aof"

# 写入策略
appendfsync everysec

# AOF 重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

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

# 异常处理
aof-load-truncated yes
aof-rewrite-incremental-fsync yes

监控和运维

关键监控指标

bash
redis-cli INFO persistence
# RDB 相关
rdb_changes_since_last_save:0      # 距离上次快照的变更次数
rdb_last_save_time:1700000000      # 上次快照时间
rdb_last_bgsave_status:ok         # 上次 bgsave 状态
rdb_last_bgsave_time_sec:1        # 上次 bgsave 耗时(秒)
rdb_current_bgsave_time_sec:-1    # 当前 bgsave 耗时

# AOF 相关
aof_enabled:1                      # AOF 是否开启
aof_current_size:1073741824        # 当前 AOF 大小
aof_base_size:536870912            # 上次重写时大小
aof_pending_rewrite:0              # 是否有重写任务
aof_last_write_status:ok          # 上次写入状态
aof_last_write_buf_sizes:0,0      # 缓冲区大小

定时任务示例

bash
#!/bin/bash
# backup-redis.sh

DATE=$(date +%Y%m%d%H%M%S)

# 备份 RDB
cp /var/lib/redis/dump.rdb /backup/redis/dump-$DATE.rdb

# 备份 AOF
cp /var/lib/redis/appendonly.aof /backup/redis/appendonly-$DATE.aof

# 清理 7 天前的备份
find /backup/redis -name "*.rdb" -mtime +7 -delete
find /backup/redis -name "*.aof" -mtime +7 -delete

面试题讲解

面试题:RDB 和 AOF 哪个更好?

普通回答: 「RDB 恢复快,AOF 数据安全。」

面试官想听: 「这要看场景。对于大多数业务,推荐混合持久化,既有 RDB 的快速恢复,又有 AOF 的数据安全。具体来说……」

面试题:Redis 持久化会阻塞吗?

普通回答: 「RDB 会阻塞。」

面试官想听: 「不完全是。SAVE 会阻塞,但 BGSAVE 是 fork 子进程处理,不阻塞主进程。唯一可能阻塞的情况是……」

面试题:同时开启 RDB 和 AOF,Redis 会加载哪个?

普通回答: 「AOF。」

面试官想听: 「Redis 优先加载 AOF。如果 AOF 开启,会优先用 AOF 恢复数据……」

总结

特性RDBAOF混合持久化
持久化方式快照命令追加RDB + AOF
数据完整性较低
恢复速度
文件大小中等
性能影响fork 时短暂阻塞持续 I/O适中
推荐程度一般推荐强烈推荐

留给你的问题

假设你的 Redis 开启了混合持久化,某天磁盘损坏了,只有内存数据还在。

这种情况下,应该用 RDB 恢复还是 AOF 恢复?哪个能恢复更多数据?

提示:考虑两种持久化的数据时效性。

基于 VitePress 构建