BGREWRITEAOF导致used_memory_rss翻倍是因双缓冲与COW共同作用:主进程维护新旧AOF缓冲区,fork子进程后大Key修改、哈希扩容等触发批量页复制,RSS飙升1.5–2倍;used_memory不计AOF缓冲与COW页,OOM killer实际监控的是used_memory_rss。

为什么BGREWRITEAOF会让used_memory_rss翻倍
根本不是Redis“写得慢”,而是双缓冲 + COW共同作用的结果:bgrewriteaof启动后,主进程必须同时维护两套AOF缓冲区——旧AOF追加缓冲和新重写命令缓冲;与此同时,fork出的子进程靠Linux的COW共享内存页,一旦主线程修改大Key、触发哈希表扩容或执行批量HSET/DEL,就会批量复制内存页,RSS直接跳升1.5–2倍。
常见错误现象包括:used_memory_rss > 2 * used_memory、dmesg | tail出现Killed process (redis-server)、INFO persistence里aof_rewrite_in_progress长期为1但aof_rewrite_buffer_length持续增长。
-
used_memory只统计Redis内部数据结构,不包含AOF缓冲区和COW复制页;真正被OOM killer盯上的是used_memory_rss - 即使
mem_fragmentation_ratio正常(比如1.2),只要used_memory_rss突增,就说明COW压力已实质性爆发 - 临时文件写入本身不占Redis进程内存,但Linux页缓存会悄悄吃掉大量
rss,尤其当新AOF >10GB时
auto-aof-rewrite-min-size设太低反而雪上加霜
很多运维看到AOF膨胀就急着把auto-aof-rewrite-min-size从默认64mb砍到8mb,结果换来更频繁的fork()风暴——每次重写都是一次fork,而高频fork在内存碎片率高(mem_fragmentation_ratio > 1.5)时极易失败,日志里出现Can't rewrite append only file: No space left on device,其实磁盘没满,是内核因vm.overcommit_memory=0拒绝分配虚拟内存。
实操建议:
-
auto-aof-rewrite-percentage保持50~100区间,低于50必须同步调高hz并确认maxmemory余量充足 -
auto-aof-rewrite-min-size下限取决于实例内存:≤4GB实例可设16mb,≥16GB建议保留64mb以上 - 绝对不要设为0——那等于禁用自动重写,
DEL冗余只会越积越多
aof-rewrite-incremental-fsync到底有没有用
这个配置项(默认yes)控制子进程重写时是否分批刷盘。开启后,子进程每写入32MB就调用一次fdatasync(),避免单次刷盘阻塞过久;但它**不减少内存占用**,也不缓解COW压力,只是降低磁盘IO毛刺。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
真正影响内存的关键点在于:它无法阻止页缓存堆积,且在慢速磁盘上可能延长重写时间,间接导致aof_rewrite_buffer_length持续累积,推高主进程缓冲区内存。
- SSD环境可保持
yes,NVMe盘甚至可设aof-rewrite-incremental-fsync 64mb进一步摊薄IO - HDD环境若发现重写耗时 >300s,建议关掉(
no),让子进程攒够更大块再刷,缩短整体时间窗口 - 无论开闭,都必须配
no-appendfsync-on-rewrite yes,否则主线程appendfsync everysec会和子进程抢IO,加剧延迟
混合持久化才是解决冗余DEL的根本手段
纯AOF重写只能合并同一key的多次操作(如100次INCR→1次SET),但对已被淘汰key的残留DEL完全无感——因为这些key在内存里已不存在,重写子进程无法识别其无效性。
而aof-use-rdb-preamble yes开启混合持久化后,重写子进程先以RDB格式dump当前内存快照,再追加增量命令;那些早已被allkeys-lru淘汰、内存中根本不存在的key,其后续DEL自然不会进入新AOF文件。
- 必须搭配
auto-aof-rewrite-min-size下调使用,否则小AOF文件根本触发不了重写 - RDB preamble部分不记录过期时间,所以
volatile-*淘汰策略下仍需确保业务层合理设置TTL - 升级到Redis 7+后,可进一步启用
active-defrag-ignore-bytes 100mb,在重写期间主动规避内存碎片干扰
最常被忽略的一点:重写完成瞬间,旧AOF缓冲区不会立即释放,而是等子进程退出后由主线程清理——这意味着used_memory_rss回落有数秒延迟,监控告警阈值必须预留这个缓冲窗口。

















