淘汰策略本身不导致aof膨胀,但已淘汰key的冗余del命令会持续写入aof;必须配合调低auto-aof-rewrite-min-size、启用混合持久化(aof-use-rdb-preamble yes)才能根治。

直接说结论:淘汰策略本身不会导致 AOF 膨胀,但 DEL 指令被记录进 AOF 后,若对应键早已因淘汰策略被删,这些 DEL 就成了冗余命令——它们不改变数据状态,却持续增大 AOF 文件。靠单纯调 auto-aof-rewrite-percentage 无法根治,必须配合 auto-aof-rewrite-min-size 和混合持久化。
为什么淘汰策略 + DEL 会埋下膨胀隐患
Redis 的淘汰策略(如 allkeys-lru)是在内存不足时主动驱逐 key,这个过程**不产生 AOF 日志**;但业务代码里显式调用的 DEL、EXPIRE 等命令仍会被追加到 AOF。如果某个 key 已被 LRU 淘汰,后续再执行 DEL key,该命令实际什么也不做,却照常记入 AOF——重写前它一直躺在文件里,且无法被自动识别为无效。
常见错误现象:
- 监控发现
aof_current_size持续增长,但used_memory稳定甚至下降 -
redis-cli INFO persistence显示aof_pending_rewrite长期为 0,但重写迟迟不触发 - 手动执行
BGREWRITEAOF后,新 AOF 文件大小仅略小于旧文件(说明冗余未被有效清理)
auto-aof-rewrite-min-size 才是真正起效的门槛
auto-aof-rewrite-percentage 只控制“相对增长比例”,而 auto-aof-rewrite-min-size 是硬性下限——哪怕比例达标,只要当前 AOF 小于该值,重写就不会启动。高频小写入场景下,AOF 增长慢、绝对值长期卡在阈值以下,重写就永远等不来。
实操建议:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 把
auto-aof-rewrite-min-size从默认64mb降到16mb或8mb(尤其当内存 ≤4GB 时) -
auto-aof-rewrite-percentage设为50(不是 0!设 0=禁用自动重写) - 确保
aof-load-truncated为yes,防止重写中断后加载失败
必须开启混合持久化(aof-use-rdb-preamble yes)
纯 AOF 重写只能合并同 key 的多次操作(如 100 次 INCR → 1 次 SET),但对已淘汰 key 的残留 DEL 无能为力;而混合持久化(Redis 4.0+)让重写子进程先 dump 当前内存快照为 RDB 格式,再追加增量命令——那些已被淘汰、内存中根本不存在的 key,其 DEL 自然不会出现在新文件里。
关键点:
- 配置项是
aof-use-rdb-preamble yes,不是aof-use-rdb或其他变体 - 开启后,新 AOF 文件开头是二进制 RDB 数据(可被
redis-check-aof --fix识别),后面才是文本命令 - 4.0 之前版本无法加载该文件,升级前需确认客户端兼容性
别忽略 fork 压力和 overcommit 配置
AOF 重写本质是 fork() 子进程遍历内存,若实例内存 >4GB,fork 耗时陡增,可能引发超时或阻塞。此时调低重写参数只是治标。
更治本的做法:
- 将
vm.overcommit_memory设为1(允许 fork 时过度分配虚拟内存) - 用
maxmemory严格限制 Redis 实例内存上限(例如2g),避免单实例失控 - 拒绝“一个实例扛所有热数据”的架构,按业务域拆分 Redis 实例
重写是否真生效,不能只看文件大小变化,得盯住 aof_base_size 是否随每次重写稳定回落——如果它越写越大,说明重写没真正精简掉冗余,大概率是混合持久化没开或 min-size 还卡在默认值。










