volatile-lfu仅淘汰设置了TTL的key,按访问频率最低优先;allkeys-lfu则对所有key统一按LFU淘汰。核心区别在于淘汰范围:前者保护永久key,后者无差别处理。

volatile-lfu 是什么,和 allkeys-lfu 有什么区别
volatile-lfu 只对设置了 EXPIRE(即有 TTL)的 key 生效;没设过期时间的 key 完全不参与淘汰。而 allkeys-lfu 对所有 key 一视同仁。如果你的业务里只有部分数据需要缓存时效性(比如 session、token),但其他数据是长期驻留的(如配置、字典表),volatile-lfu 就更安全——它不会误删你本意要永久保留的 key。
注意:volatile-lfu 在内存不足时,只在带 TTL 的 key 中按 LFU 规则筛选;如果此时根本没有带 TTL 的 key,Redis 会直接拒绝写入(报错 (error) OOM command not allowed when used memory > 'maxmemory'.),而不是 fallback 到其他策略。
如何正确配置 volatile-lfu 策略
必须同时满足两个条件,volatile-lfu 才会真正生效:
-
maxmemory必须明确设置(比如2gb或512mb),不能为0或注释掉 -
maxmemory-policy必须设为volatile-lfu(不是lfu、volatile-lru等)
配置方式有两种:
• 在 redis.conf 中写死:
maxmemory 1gb maxmemory-policy volatile-lfu
• 运行时动态修改(需确认实例允许 config rewrite):
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
CONFIG SET maxmemory 1073741824 CONFIG SET maxmemory-policy volatile-lfu
改完建议用 CONFIG GET maxmemory* 核对,避免拼写错误或空格干扰。
为什么访问了 key 却没看到频率上升
LFU 频率不是简单累加,而是受三个机制共同约束:
-
lfu-log-factor:默认为10,值越小,低频 key 增长越快;调大(如100)会让高频 key 更容易“脱颖而出” -
lfu-decay-time:单位是分钟,默认1,表示每过 1 分钟自动衰减一次 counter;若设为0,则完全不衰减(不推荐,易导致旧热点长期霸榜) - 初始值陷阱:新 key 插入时
logc不是0或1,而是5—— 所以刚 set 的 key 实际已有“基础热度”,不会一上来就被淘汰,但也意味着你需要多次访问才能明显提升它的 rank
验证是否生效?用 OBJECT FREQ <key> 查看当前对数计数器值(返回 0–255 的整数),配合 OBJECT IDLETIME <key> 看距上次访问秒数,能交叉判断衰减和增长是否在跑。
容易被忽略的兼容性与监控盲区
Redis 4.0+ 才支持 volatile-lfu,但 4.0–6.0 版本的 OBJECT FREQ 返回值是近似值(因概率递增 + 衰减机制),不能当作精确访问次数使用;6.2+ 引入了更稳定的采样逻辑,但依然不保证绝对准确。
真正麻烦的是监控:Prometheus 的 redis_exporter 默认不暴露 per-key 的 freq 数据,INFO keyspace 也只给命中/丢失统计,没法直接看出哪些 key 正在被 LFU “盯上”。如果要做淘汰前预警,得自己用 SCAN 配合 OBJECT FREQ 定期采样,且注意别在高峰期扫全库——否则可能触发慢日志甚至阻塞。
最常踩的坑是:开了 volatile-lfu,但忘了给 key 设 TTL,结果所有写入都失败却不明白为什么。记住:没 EXPIRE,就没有 LFU。

















