AOF重写能清除过期数据,因其基于内存快照重建命令集,跳过已过期key;需同时满足auto-aof-rewrite-percentage和min-size阈值才触发自动重写,手动BGREWRITEAOF更可控。

AOF 文件里堆积的过期 key 不会自动消失,靠重写才能真正清理掉。 单纯等 key 过期、或依赖 DEL 命令手动删,对 AOF 体积毫无帮助——因为过期操作本身也会被记录进 AOF,甚至可能留下 EXPIRE + DEL 两条冗余命令。真正起效的,是 AOF 重写机制在重建文件时跳过已过期数据这一行为。
为什么 AOF 重写能清除过期数据
AOF 重写不是压缩旧文件,而是“从内存快照出发,重新生成最小命令集”。它不读原 AOF 文件,而是遍历当前数据库状态,只对仍存活的 key 生成写入命令。那些已过期、被惰性删除或定期删除策略清理掉的 key,根本不会出现在新 AOF 中。
常见错误现象:redis-cli --bigkeys 显示 key 数量少,但 AOF 文件持续膨胀;INFO persistence 中 aof_current_size 远大于 db0:keys=xxx 所暗示的数据量 —— 这正是过期数据滞留在 AOF 中的典型信号。
- 重写过程不依赖 AOF 文件内容,只依赖 fork 时刻的内存快照(含已清理的过期 key)
- 子进程执行重写时,主线程仍在服务请求,但所有新写入命令会双写到
aof_buf和aof_rewrite_buf - 重写完成后,
aof_rewrite_buf中的增量会被追加到新文件末尾,确保不丢数据
触发重写的两个配置必须同时满足
仅靠 auto-aof-rewrite-percentage 不够,很多线上环境因 AOF 初始体积小,长期达不到 min-size 下限而无法触发重写。
例如:刚启动 Redis 后首次写入,AOF 只有 2MB,即使后续增长到 5MB(+150%),若 auto-aof-rewrite-min-size 64mb,也不会触发。
-
auto-aof-rewrite-percentage 100:表示当前 AOF 大小需超过“上次重写后大小”的 2 倍 -
auto-aof-rewrite-min-size 64mb:硬性门槛,低于此值直接忽略 percentage 判断 - 两者是 AND 关系,缺一不可;建议生产环境将
min-size设为 16mb 或 32mb,避免冷启后长期不重写
手动触发重写比等自动更可控
自动重写时机不可控,可能在流量高峰时触发 fork,引发短暂延迟;而手动执行 BGREWRITEAOF 可选低峰期操作,且能立刻观察效果。
使用场景:发现 aof_current_size 突增、磁盘空间告警、或批量删除大量 key 后想立即瘦身 AOF 文件。
- 执行
redis-cli BGREWRITEAOF,返回Background append only file rewriting started即表示已提交任务 - 通过
INFO persistence观察aof_rewrite_in_progress:1和aof_rewrite_scheduled:0确认正在运行 - 重写期间不要执行
CONFIG SET修改auto-aof-rewrite-*参数,可能导致逻辑错乱
重写后仍没变小?检查是否真有过期数据可清理
如果重写前后 aof_current_size 几乎不变,大概率说明当前内存中没有大量已过期但未被清理的 key —— 也就是 AOF 里其实没多少“假数据”。
验证方式:redis-cli --scan --pattern "*" | xargs -I {} redis-cli TTL {} | grep -v "^-2$|^$-1$" | wc -l(统计仍有有效 TTL 的 key 数量),再对比 DBSIZE。若两者接近,说明过期 key 已基本清完,重写自然减幅有限。
容易踩的坑:maxmemory 配置 + LRU/LFU 驱逐策略下,key 被驱逐后仍可能残留在 AOF 中(因为驱逐不产生 DEL 命令),此时重写也无济于事——必须靠重写 + 主动 FLUSHALL 或重启来彻底刷新状态。











