混合持久化仍触发bgrewriteaof,重写输出为“rdb头部+aof尾部”格式,需通过重写生成含redis0009魔数的新aof文件,而非跳过重写或拼接dump.rdb。

混合持久化不是跳过AOF重写,而是重写时改用RDB+AOF混合格式
混合持久化模式下依然会触发 bgrewriteaof,是因为它本质仍是AOF机制的一部分——只是重写过程的输出格式变了。Redis不会因为开了 aof-use-rdb-preamble yes 就停止重写;相反,它必须通过重写来生成那个“RDB头部 + AOF尾部”的新文件。
常见误解是以为混合模式 = “不重写”,实际恰恰相反:只有执行重写,才能把内存当前状态以RDB格式塞进AOF文件开头。不重写的话,appendonly.aof 里就只有原始追加的命令,永远不会有RDB魔数 REDIS0009 开头。
- 触发条件完全没变:
auto-aof-rewrite-percentage和auto-aof-rewrite-min-size仍起作用 - 重写逻辑变了:子进程不再逐条反推命令,而是先做一次RDB序列化(类似
bgsave),再把重写开始后的新命令以RESP格式追加 - 旧AOF文件不会被直接复用——重写总是生成全新文件,然后原子替换
为什么不能直接用现有RDB文件拼接AOF?
Redis不把 dump.rdb 和 appendonly.aof 简单合并,是因为二者时间点不一致、状态不可对齐:
-
dump.rdb是某个过去时刻的快照,而AOF里可能包含该快照之后又删除/覆盖的key,直接拼接会导致数据矛盾 - 混合模式要求“RDB部分”必须精确反映重写开始时的内存快照,且后续AOF命令必须是从那一刻起新增的——这个一致性只能靠重写期间的原子快照保证
- Redis硬编码了加载逻辑:启动时只认
appendonly.aof(或appendfilename指定名),dump.rdb完全被忽略,所以根本不存在“读两个文件再合并”的路径
重写日志体积变小了,但重写本身开销未必降低
混合模式让最终AOF文件比纯AOF小,但重写过程反而更吃资源:
- 要同时维护两套缓冲区:旧AOF的增量缓冲、新AOF的RDB+命令双段缓冲
- RDB序列化阶段仍需 fork() + COW,大内存实例下 fork 耗时和内存占用跟纯RDB一样高
- 如果
appendonly.aof原本就很大,重写期间磁盘IO压力可能比纯AOF重写更高(RDB块是二进制流,写入带宽密集)
所以别指望开了混合模式就“重写变快”——它优化的是重启恢复速度,不是重写耗时。
如何确认你看到的确实是混合重写日志?
不要只看配置项返回 yes,得验证文件内容是否真含RDB头:
- 执行
xxd appendonly.aof | head -10,开头应出现REDIS0009(或对应版本号),而不是*3\r\n$3\r\nSET这类RESP命令 - 用
redis-cli config get aof-use-rdb-preamble确认是["aof-use-rdb-preamble","yes"],注意大小写和引号 - 检查
redis.conf中appendonly yes必须为 true,否则混合模式根本不启动
最容易被忽略的是:混合模式下,dump.rdb 文件即使存在,也完全不参与启动加载——它只是个残留文件,删不删都不影响恢复逻辑。











