oom是内存碎片导致的“假满”:used_memory未超maxmemory但used_memory_rss过高,mem_fragmentation_ratio>1.5即需警惕;redis 4.0+可通过config set activedefrag yes等动态开启自动整理。

为什么 used_memory 没超 maxmemory 却报 OOM?
这是内存碎片最典型的“假满”现象:Redis 显示 used_memory 还剩几百 MB,但执行写命令时却直接返回 OOM command not allowed when used memory > 'maxmemory'。根本原因不是数据真满了,而是 used_memory_rss(操作系统分配的物理内存)严重膨胀,jemalloc 无法从碎片中凑出一块连续内存来满足当前申请——哪怕总空闲字节数看起来足够。
怎么快速确认是碎片惹的祸?
立刻查 info memory,重点关注三行:
-
used_memory:Redis 自己“认为”用了多少(干净数据+缓冲区等) -
used_memory_rss:系统实际塞给它的物理内存(含碎片+共享库+堆栈) -
mem_fragmentation_ratio:=used_memory_rss / used_memory,>1.5 就得警惕,>2.0 基本就是碎片卡死你了
如果 mem_fragmentation_ratio > 1.5,且 used_memory 明显低于 maxmemory,那 90% 是碎片导致的伪 OOM。
Redis 4.0+ 怎么开自动碎片整理?
别重启!用 config set 动态开启,但参数必须配对生效:
-
config set activedefrag yes:开关打开(必须第一步) -
config set active-defrag-ignore-bytes 100mb:碎片绝对值 ≥100MB 才触发(防小碎屑白忙) -
config set active-defrag-threshold-lower 10:碎片占比 ≥10% 才启动(两个条件需同时满足) -
config set active-defrag-cycle-min 25和active-defrag-cycle-max 75:控制整理过程吃 CPU 的比例,避免卡住主线程
⚠️ 注意:active-defrag-ignore-bytes 和 active-defrag-threshold-lower 是“与”关系,缺一不可;改完不会立刻生效,要等下一次满足条件的内存分配/释放事件触发。
为什么开了 activedefrag 还没反应?
常见盲区:
- 你的 Redis 版本必须 ≥4.0(
redis-server --version确认),旧版只能靠重启或换分配器 - 整理只在内存分配器(jemalloc)层面进行,不涉及 RDB/AOF 文件或 Swap,别指望它清理磁盘文件
- 如果
mem_fragmentation_ratio - 大键(>1MB)反复
APPEND或SET修改,会产生巨量外部碎片,自动整理可能跟不上节奏,得配合拆键或定期MEMORY PURGE(6.0+)
真正卡住的点往往不在开关开没开,而在阈值设太保守、或者根本没意识到 rss 和 used_memory 不是一回事。








