淘汰频率突然升高是因为内存持续逼近maxmemory上限,主因是写入速率长期超过内存释放速率,或淘汰策略与数据访问模式错配;如volatile-*策略下短TTL键集中到期,或allkeys-lru误踢新冷数据,亦或LFU计数器配置不当、内存碎片率过高(>1.5)导致实际可用内存不足。

为什么淘汰执行频率会突然变高?
淘汰频率高不是 Redis “变勤快了”,而是内存持续逼近 maxmemory 上限,触发了更密集的驱逐检查。根本原因通常是:写入速率长期 > 内存释放速率,或淘汰策略与数据访问模式严重错配。比如大量短 TTL key 集中到期(volatile-ttl 策略下),或冷热混杂但用了 allkeys-lru 导致频繁踢掉刚写入的“新冷数据”。
先看是不是 volatile-* 策略在扎堆淘汰
如果你用的是 volatile-lru、volatile-ttl 或 volatile-lfu,而业务又习惯批量设置整数秒 TTL(如 60s、300s),就会在每 100ms 的定期扫描周期里集中发现一堆剩余 TTL ≈ 0 的 key,引发脉冲式 evicted_keys 增长和主线程阻塞。
- 查证方式:
INFO stats中观察evicted_keys是否呈锯齿状跳升,同时expired_keys是否同步激增 - 临时缓解:立刻切到
allkeys-lfu,并确保lfu-log-factor≥ 10、lfu-decay-time= 1 - 根治动作:停用物理 TTL,改用逻辑过期(value 内嵌
exp字段),把淘汰决策权交给 LFU 计数器,而非时间戳
allkeys-lfu 下还是抖?检查 LFU 计数器是否被“卡住”
allkeys-lfu 不是开了就自动平滑——它依赖每次访问更新计数器。如果 key 写入后长期不读(比如异步写入的配置项、日志缓冲),它的 LFU 值永远为 0,在淘汰队列里排最前,反而比真实冷数据还容易被踢。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 验证方法:用
OBJECT FREQ key抽样几个高频/低频 key,看计数器是否随访问增长 - 常见陷阱:没配
lfu-log-factor(默认 10,太小会导致计数器饱和过快)或lfu-decay-time(默认 1,太大会让旧高频 key 长期霸榜) - 调优建议:对写多读少场景,可设
lfu-log-factor 100+lfu-decay-time 1,让计数器更敏感、衰减更快
别忽略内存碎片和 jemalloc 的隐性开销
即使 used_memory 没满,used_memory_rss / used_memory > 1.5 就说明内存碎片严重。jemalloc 在高碎片下 rehash 分配器会吃 CPU,间接抬高淘汰触发频率——因为碎片导致实际可用内存远低于理论值。
- 紧急处理:
MEMORY PURGE(仅 jemalloc 有效)或重启实例(生产慎用) - 长期方案:开启
activedefrag yes,并调大active-defrag-threshold-lower(默认 10,建议 25)和active-defrag-cycle-min(默认 5,建议 25) - 监控重点:盯住
mem_fragmentation_ratio和mem_allocator字段,别只看used_memory
真正降压的关键不在“少淘汰”,而在让淘汰行为脱离时间驱动、避开 CPU 敏感时段、并和业务访问节奏对齐。LFU 是解药,但必须配对逻辑过期和碎片治理,三者缺一不可。

















