Skip to content

03.3 - 混合持久化与最佳实践

定位: Redis 4.0 引入的混合持久化——整合 RDB 的快速恢复和 AOF 的低丢失 面试高频度: ⭐⭐⭐⭐ 考查方式: 混合持久化原理、AOF+RDB 的加载顺序、生产配置方案


一、这是什么?为什么需要它?

是什么

混合持久化(Redis 4.0+)在 AOF rewrite 时,先生成一个 RDB 快照作为基线数据,再追加 RDB 快照之后的增量命令。AOF 文件 = RDB 头部 + AOF 增量尾部。

为什么需要混合持久化?

RDB 单独使用的痛点: 电商大促场景:

  • 上一轮 RDB 在 12:00 完成
  • 12:01-12:15 产生 100 万次写入
  • 12:15 宕机
  • rdb_last_save_time: 12:00
  • 100 万次写入丢失

AOF 单独使用的痛点: 100GB 数据的 Redis 宕机重启:

  • 纯 AOF:重放 100 亿条命令
  • 恢复需要 1 小时,业务不可用 1 小时!

混合持久化: 既开 RDB 又开 AOF:

  • 先用 RDB 做"快速基础恢复"(几分钟)
  • 再用 AOF 补"增量数据"(十多秒)
  • 恢复时间 = RDB加载时间 + AOF增量时间
  • 比纯 AOF 快 10-100 倍

二、原理拆解

2.1 混合持久化的 AOF 文件格式

2.2 加载顺序与流程

AOF 加载的两种子情况:

  • 普通 AOF: 从头到尾重放所有命令 O(N)
  • 混合 AOF: 先加载 RDB 段(Jemalloc 直接加载),再执行 AOF 段的增量命令
  • 加载速度 = RDB 加载时间 + 增量命令执行时间

2.3 生产配置推荐

conf
# ============ 持久化配置推荐 ============

# 1. AOF 开启(推荐)
appendonly yes
appendfsync everysec

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

# 3. AOF 自动 rewrite 策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 4. RDB 保留策略(用于灾难恢复)
save 900 1
save 300 10
save 60 10000

# 5. 停止写入策略(磁盘满时保护)
no-appendfsync-on-rewrite yes  # rewrite 期间不 fsync,避免磁盘竞争

# 6. 子进程写入策略
rdbcompression yes      # RDB 压缩(节省磁盘但多耗 CPU)
rdbchecksum yes         # RDB 校验(安全但多耗 5-10% CPU)

2.4 不同场景的持久化策略

yaml
场景: "缓存"
  - 数据可丢失
  - 关闭持久化(最大性能)
  - 配置: save ""(关闭 RDB)+ appendonly no

场景: "缓存+持久化"
  - 数据不能全丢
  - 主库开 AOF everysec + 混合持久化
  - 从库开 RDB(用于备份/从节点恢复)

场景: "数据库级使用"
  - 数据不能丢
  - AOF everysec + always(关键数据)
  - 主库 AOF + 从库 RDB 双保险
  - 定期 S3 备份 RDB 文件

场景: "大容量 Redis(>32GB)"
  - fork 代价大 → 只在从节点做持久化
  - 主节点不持久化(关闭 RDB+AOF)
  - 从节点持久化 + 定期备份
  - 主节点宕机→从节点升级为主

三、图解全景


四、实战验证

4.1 查看当前持久化配置

bash
redis-cli

# AOF 状态
127.0.0.1:6379> CONFIG GET appendonly
1) "appendonly"
2) "yes"

# 混合持久化
127.0.0.1:6379> CONFIG GET aof-use-rdb-preamble
1) "aof-use-rdb-preamble"
2) "yes"

# fsync 策略
127.0.0.1:6379> CONFIG GET appendfsync
1) "appendfsync"
2) "everysec"

# RDB 规则
127.0.0.1:6379> CONFIG GET save
1) "save"
2) "3600 1 300 100 60 10000"  # 多条规则空格分隔

4.2 混合持久化文件分析

bash
# 确认 AOF 文件已开启混合模式
file /var/lib/redis/appendonly.aof
# appendonly.aof: Redis AOF file, RDB preamble (mixed format)

# 查看混合 AOF 文件头部
hexdump -C /var/lib/redis/appendonly.aof | head -5
# 00000000  52 45 44 49 53 30 30 30  39  fa ... (REDIS0009 是 RDB 头)

# 对比两种模式的 AOF 恢复时间
# 测试 10GB Redis 的恢复时间
# 纯 AOF: ~30 分钟
# 混合 AOF: ~3 分钟(RDB 加载 2 分钟 + 增量 1 分钟)

4.3 模拟崩溃恢复测试

bash
# 1. 开启混合持久化
redis-cli CONFIG SET appendonly yes
redis-cli CONFIG SET aof-use-rdb-preamble yes

# 2. 写入 10000 个 key
for i in $(seq 1 10000); do
  redis-cli SET "key:$i" "value:$i" > /dev/null
done

# 3. 手动触发混合持久化(BGREWRITEAOF)
redis-cli BGREWRITEAOF
sleep 5

# 4. 再写入一些数据(模拟增量)
redis-cli SET "last-key" "should-be-there"

# 5. 模拟崩溃
sudo systemctl stop redis

# 6. 确认 AOF 文件存在
ls -la /var/lib/redis/appendonly.aof

# 7. 启动
sudo systemctl start redis

# 8. 验证数据
redis-cli DBSIZE
# (integer) 10001  ← 所有 key 都恢复了
redis-cli GET "last-key"
# "should-be-there"  ← 崩溃前的增量数据也在

五、面试视角

追问答案要点
混合持久化的 AOF 文件结构?RDB 头部(全量快照)+ AOF 尾部(增量命令),BGREWRITEAOF 时生成
混合持久化的加载流程?Redis 启动 → 加载 AOF 文件 → 发现 RDB 头 → 先加载 RDB 段 → 再执行 AOF 增量命令
为什么混合持久化恢复快?RDB 段是二进制内存快照(Jemalloc 直接加载),只需回放少量 AOF 增量命令
生产推荐的持久化方案?主节点 AOF everysec + 混合模式;从节点开 RDB;或主节点不持久化,从节点持久化
大内存实例的持久化策略?主节点关闭持久化(避免 fork 阻塞),从节点开启 AOF+RDB;主从切换时从提升为主
混合持久化的缺点?AOF 文件比纯 RDB 大,比纯 AOF 小(折中);rewrite 时仍需要 fork
如果 AOF 和 RDB 同时开,Redis 用哪个恢复?优先用 AOF(数据最完整);AOF 不存在则用 RDB

📚 相关链接

  • **RDB 快照** — 混合持久化的 RDB 部分
  • **AOF 日志** — 混合持久化的 AOF 部分
  • **主从复制** — 全量复制依赖 RDB
  • ← 返回 **持久化索引**

Knowledge4J — Java 知识库