aof重写期间易触发异常淘汰,因bgrewriteaof fork子进程读取全量键状态、新命令持续追加至旧aof及重写缓冲区,导致used_memory_rss快速突破maxmemory阈值,叠加lru类策略实时淘汰,引发cpu飙升与延迟毛刺。

AOF重写与内存淘汰策略在Redis 7.0中不会直接冲突,但会相互放大资源压力——尤其当maxmemory设置偏小、auto-aof-rewrite-percentage又过高时,重写过程可能触发大量淘汰,甚至导致写阻塞或OOM。
为什么AOF重写期间容易触发异常淘汰
Redis 7.0 的 AOF 重写(BGREWRITEAOF)本身不操作主数据库,但它会 fork 子进程并构建一个精简的命令序列。这个过程需读取当前所有键的状态,而如果此时 maxmemory 已逼近上限,且淘汰策略为 allkeys-lru 或 volatile-lru,主线程在重写期间仍持续接收写请求,就可能瞬间突破内存阈值。
更关键的是:重写过程中,新写入的命令仍会追加到旧 AOF 文件,并同时写入 aof_rewrite_buf(重写缓冲区),该缓冲区本身也占用内存——它不是固定大小,而是随写入量线性增长。若此时已有大量待淘汰键,used_memory_rss 可能快速超过 maxmemory,触发连续淘汰,CPU 升高、延迟毛刺明显。
- 典型现象:
INFO memory中mem_fragmentation_ratio> 1.5,evicted_keys在重写开始后突增 - 根本原因:重写不“暂停淘汰”,而内存压力是实时累积的
- Redis 7.0 默认启用
lazyfree-lazy-eviction yes,但仅对删除操作异步化,无法缓解重写期间的内存申请压力
调整 auto-aof-rewrite-percentage 要看内存水位,不是只看AOF大小
很多人把 auto-aof-rewrite-percentage 当成纯磁盘策略调优项,但在 7.0+ 版本中,它必须和内存使用联动判断。因为重写过程本身吃内存,若 AOF 膨胀率高往往意味着写密集,而写密集 + 内存吃紧 = 高风险。
建议用以下逻辑动态评估是否该降低该值:
- 如果
used_memory / maxmemory > 0.7,且auto-aof-rewrite-percentage仍为默认100,应立即降至60~80 - 若使用
allkeys-lfu策略,可适当放宽至90(LFU 更抗突发写,淘汰更平滑) - 绝对避免设为
0或off:AOF 不重写 → 文件无限膨胀 → 启动恢复时间不可控,且redis-check-aof修复失败概率陡增
配置示例(redis.conf):
auto-aof-rewrite-percentage 70 auto-aof-rewrite-min-size 32mb
注意:auto-aof-rewrite-min-size 也要同步下调——SSD 环境下 32MB 比默认 64MB 更早触发重写,减少单次重写数据量,间接降低内存峰值。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
手动触发 BGREWRITEAOF 前必须检查三项指标
自动触发靠参数,但生产环境强烈建议改为主动控制。执行前务必确认以下三值均处于安全区间:
used_memory_rss / used_memory (碎片率正常,说明内存分配健康)-
mem_allocator是jemalloc(Redis 7.0 默认,比 libc malloc 更可控;若为libc,重写期间更容易 OOM) -
evicted_keys近 5 分钟增量为0(证明当前无淘汰压力)
检查命令组合:
redis-cli INFO memory | grep -E "(used_memory|used_memory_rss|mem_fragmentation_ratio|evicted_keys)" redis-cli INFO memory | grep mem_allocator
只要其中任一条件不满足,就应推迟重写,先调大 maxmemory 或清理无效 key,而不是硬扛。
混合持久化(aof-use-rdb-preamble)不能绕过淘汰压力
Redis 4.0 引入、7.0 默认开启的 aof-use-rdb-preamble yes,会让 AOF 文件开头包含一段 RDB 格式数据,后续才是命令追加。这确实加快了启动加载速度,但它不减少重写过程中的内存开销——RDB preamble 仍需全量序列化当前内存状态,一样要遍历所有 key,一样受 maxmemory 和淘汰策略影响。
换句话说:混合持久化优化的是“恢复阶段”,不是“重写阶段”。如果你的问题出在重写卡顿或触发淘汰,开不开 preamble 没区别。
真正有效的缓解手段只有两个:压低重写频率(通过更激进的 auto-aof-rewrite-percentage)、或给足内存余量(maxmemory 至少留 25% buffer)。后者在容器化部署中常被忽略——K8s limit 设为 4Gi,但 Redis 配 maxmemory 4gb,等于没留余量,重写必抖。










