CONFIG GET maxmemory-policy 返回的策略名不等于实际生效,如返回volatile-lru但无key设TTL,则等效noeviction导致OOM;须用INFO keyspace比对expires数量与DBSIZE,并监控evicted_keys、mem_fragmentation_ratio验证真实效果。

CONFIG GET maxmemory-policy 返回值是否匹配业务语义
直接执行 CONFIG GET maxmemory-policy 查到的策略名,不等于它在当前数据分布下真能起效。比如返回 volatile-lru,但你所有 key 都没设 TTL,那这个策略就完全不触发淘汰——等同于 noeviction,写入会报 (error) OOM command not allowed when used memory > 'maxmemory'。
检查方式:INFO keyspace 看各 db 的 expires= 数量;再用 DBSIZE 对比,如果 expires 远小于 keys 总数,说明 volatile-* 类策略基本失效。
- volatile-* 策略只对
SET key val EX 3600这类显式带过期时间的 key 生效 - allkeys-* 策略才管没设 TTL 的 key,但可能误杀长期有效的配置类数据
- 如果业务中大量使用永不过期 key(如用户基础信息),又配了
volatile-ttl,内存就卡死不动
INFO memory 中 used_memory_rss 和 used_memory 差值过大
当 used_memory_rss / used_memory > 1.5(常见阈值),说明内存碎片严重,Redis 虽然逻辑上“删了 key”,操作系统却没回收物理内存,maxmemory 淘汰机制也无从下手——它只看 used_memory 是否超限,而碎片会让 used_memory_rss 持续高位。
典型诱因:HSET user:1001 profile ... 这种大 hash 被反复增删字段、或 LPUSH/LPOP 频繁操作 list 导致内存分配器无法合并空闲块。
- 用
redis-cli --bigkeys扫出 >1MB 的 key,优先处理它们 - 观察
mem_fragmentation_ratio字段,>2.0 就该警惕 - 重启实例是唯一彻底清理碎片的方式(需配合主从切换或集群 failover)
OBJECT FREQ 对 LFU 策略的实际反馈是否可信
OBJECT FREQ 返回值不是实时计数,而是基于衰减采样的估算,且仅在启用 allkeys-lfu 或 volatile-lfu 时更新。如果你看到热 key 的 FREQ 值长期卡在 0 或 1,不是它不热,很可能是采样周期太长或访问模式不匹配 LFU 的“频次”定义(比如每分钟只访问一次,LFU 认为冷)。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
验证方法:对一个已知高频访问的 key(如 cache:homepage)连续 GET 10 次,再立刻 OBJECT FREQ,若仍 ≤1,说明 LFU 当前未生效或被干扰。
- LFU 的计数器有衰减机制,默认每分钟右移 1 位(即除以 2),低频访问会被快速抹平
- 如果业务是“每天固定时段爆发访问”,LFU 效果远不如 LRU
-
CONFIG SET lfu-log-factor 10可提升低频 key 的保留能力,但会增加 CPU 开销
淘汰发生后,INFO stats 的 evicted_keys 是否持续增长
evicted_keys 是累计值,只要它在业务高峰期稳定上涨,说明淘汰机制确实在工作;但如果它长时间为 0,而 used_memory 又紧贴 maxmemory,那问题一定出在策略匹配或碎片上。
注意:evicted_keys 不区分淘汰原因——可能是主动淘汰,也可能是过期 key 被定期删除触发的被动释放,后者不计入此指标。所以要结合 expired_keys 一起看。
- 如果
evicted_keys == 0且expired_keys也很小,基本锁定是策略配置错误或全量 key 无 TTL - 如果
evicted_keys增长但used_memory不降,大概率是碎片或大 key 占着内存不放 - 监控脚本里别只盯
used_memory,必须同时采集mem_fragmentation_ratio和evicted_keys的 delta
真实场景里最常被忽略的,是把“key 被删了”和“内存释放了”当成一回事。Redis 淘汰 key 后,内存未必还给操作系统——尤其是用了 jemalloc 且存在大量小对象分配时,这块需要单独治理。

















