6.3 混合持久化与选型 本节摘要:混合持久化(Redis 4.0 起,5.0 后默认)让 AOF 重写时把基础数据以 RDB 二进制格式写进文件头,其后的增量仍用 AOF 命令追加。恢复时先快速加载 RDB 段,再重放少量增量——既快又全,等于把前两节的两种文件焊成一个。 为什么要混合 前两节各自的软肋正好互补: 维度 | 纯 RDB | 纯 AOF | 混合 恢复速度 | 快(直接加载结果) | 慢(逐条重放命令) | 快 丢数据窗口 | 两次快照之间,可达分钟级 | fsync 策略决定,最差1秒 | 同 AOF,最差1秒 文件大小 | 最小 | 重写前偏大 | 接近 RDB 略大 混合格式的聪明之处在于重写这个时机:反正重写就是"按当前内存生成最小集",那就直接写成加载更快的
本节摘要:混合持久化(Redis 4.0 起,5.0 后默认)让 AOF 重写时把基础数据以 RDB 二进制格式写进文件头,其后的增量仍用 AOF 命令追加。恢复时先快速加载 RDB 段,再重放少量增量——既快又全,等于把前两节的两种文件焊成一个。
前两节各自的软肋正好互补:
| 维度 | 纯 RDB | 纯 AOF | 混合 |
|---|---|---|---|
| 恢复速度 | 快(直接加载结果) | 慢(逐条重放命令) | 快 |
| 丢数据窗口 | 两次快照之间,可达分钟级 | fsync 策略决定,最差1秒 | 同 AOF,最差1秒 |
| 文件大小 | 最小 | 重写前偏大 | 接近 RDB 略大 |
混合格式的聪明之处在于重写这个时机:反正重写就是"按当前内存生成最小集",那就直接写成加载更快的 RDB 编码;重写之后的增量没法预知,继续用 AOF 追加。一个文件,两种区段。

开启只需要一行:
aof-use-rdb-preamble yes
之后每次自动或手动触发的 BGREWRITEAOF 产出的就是混合文件,旧的纯 AOF 在第一次重写后自然被替换。
确认当前实例吃没吃到这个特性,两条路任选:
> CONFIG GET aof-use-rdb-preamble 1) "aof-use-rdb-preamble" 2) "yes" # 更硬核的验证:看文件头是不是RDB魔数 head -c 5 appendonly.aof REDIS # RDB段的指纹,纯AOF文件开头是星号
文件头五个字节就分清两种格式,迁移验收时用得上。还有一个兼容性提醒:混合文件只能被 4.0 及以上的实例加载,往低版本实例导入数据时要先确认版本,别让"恢复演练"变成"恢复事故"。
恢复速度的差距值得用数字感受:同一个约 8GB 的数据集,纯 AOF 重放命令约六到十分钟,混合格式先灌 RDB 段再补增量,通常一两分钟内完成——差距来自"逐条解析执行命令"与"按二进制格式直接还原结构"的固有开销。重启频率高的业务(弹性伸缩、频繁发版)对这个差距最敏感,冷启动拖十分钟,网关的超时早堆成山了。
纯缓存实例:只开 RDB 或干脆关持久化。数据可回源重建,持久化只为加速冷启动;甚至有团队用"关闭持久化加定时快照到异地"的组合,把性能榨到极致。
"关掉持久化、靠主从复制保数据"的思路要单独点破它的裂缝:主从复制是异步的,主库崩溃瞬间,从库未必有最新数据;更隐蔽的是主从可以同时坏——机房断电、同一宿主机故障、误操作把主从一起 FLUSHALL。从库是可用性方案,不是备份方案。备份的定义要满足三点:独立存放、定期轮换、恢复演练过——RDB 定时归档到对象存储才是备份,这条纪律在第 8 章的安全清单里还会出现。
会话与一般业务实例:混合持久化加 everysec。重启丢一秒通常无感;恢复速度要求中等,混合格式足够。
给"一秒窗口"画个具体的像,选型时心里更有底:启用 everysec 后,服务端每秒集中刷一次盘,崩溃时丢的是"最后一次成功 fsync 之后的那批写命令"。对会话场景,这意味着用户最近一秒的登录态变动可能回滚,重新登录即可;对购物车,最近一秒的加购可能消失,用户重加一次;对支付流水,这一秒的"已扣款"记录可能没了——前两者无感,后者就是资损。所以这一档的边界判据是:丢一秒的数据,用户是"没察觉"还是"要投诉",答案不同,档位就不同。
强一致业务实例:混合持久化加 everysec 是下限,但要点破一个事实——异步复制与 fsync 的固有窗口决定了 Redis 到不了零丢失。真正不能丢的数据(支付流水)写关系型数据库或 MQ,Redis 只做加速层。这个边界想清楚,比调任何参数都值钱。
给这个结论配一个可操作的判定流程:把"这条数据丢了会怎样"当成评审必答题——答案分三档,"回源重建"归缓存档、"用户重试一次"归一般档、"资损或合规问题"直接出 Redis 主存储的候选名单。档位定了,第 6 章三套配置模板就是查表问题,不再需要临场争论。
RDB 与 AOF 同时开时:BGSAVE 与 BGREWRITEAOF 共享 fork 开销,官方策略是两者不并发执行(一个在跑另一个排队);磁盘要承受快照全量写加日志持续写,机械盘会先成为瓶颈,固态盘基本无虞;内存峰值按一次写时复制预估。容量规划时把"持久化期间内存上浮"与"磁盘写入带宽"两项列进表格,比事后救火体面得多。
排期上还有个常被忽略的坑:自动 RDB 的触发由 save 规则驱动,自动 AOF 重写由体积百分比驱动,两者的触发时机不受你控制,可能在业务高峰撞车——虽然服务端会让它们排队执行,但排队本身就意味着"该拍的快照延迟拍了、丢失窗口变长"。所以双开实例的标配是监控里加两条曲线:rdb_bgsave_in_progress 与 aof_rewrite_in_progress,重叠或频繁触发时,把窗口参数调松,把主动触发挪到低峰。
# 存储型通用模板 appendonly yes appendfsync everysec aof-use-rdb-preamble yes auto-aof-rewrite-percentage 200 # 翻两倍才重写,减少 fork 频率 auto-aof-rewrite-min-size 2gb save 3600 1 # RDB 仅作灾备快照 dir /data/redis # 独立数据盘
配合定时任务在凌晨低峰手动 BGREWRITEAOF,白天的自动重写概率降到最低——fork 停顿对延迟敏感业务的伤害,永远值得用调度去规避。
定时任务的写法有个讲究:触发前先查一眼 INFO persistence,确认没有其他持久化任务在跑再动手;跑完记录耗时与文件体积,形成一份"重写台账"。这套小流程把"错峰"从口头纪律变成可审计的动作,交接给下一任维护者时也一目了然。
💡 关键直觉:持久化的所有选择,最后都收敛为一个问题——"丢多少数据是业务能咽下的"。把这个问题问清楚,配置表自己就写出来了。