LFU淘汰策略下冷数据滞留主因是计数器衰减过慢,默认lfu-decay-time=60秒导致低峰期冷数据频次迟迟不降;需据业务低谷时长合理调小该值(如设为300秒),并配合TTL设置、大Key拆分及避免依赖重启后归零的LFU计数。

LFU淘汰策略下,冷数据为啥还赖着不走?
Redis的allkeys-lfu或volatile-lfu策略本意是“谁最近访问少、谁先滚”,但实际中常发现:某个上周爆火的Key(比如明星热搜)明明已没人查了,却还在内存里占着坑——这不是策略失效,而是LFU计数衰减太慢。Redis用“访问频次计数器+时间衰减”双机制,而衰减节奏由lfu-decay-time控制,默认值是1分钟(60秒),意味着每分钟才把所有Key的计数器除以2。如果流量低谷期持续几小时,这个“半衰期”就太长了,冷数据计数器迟迟降不到淘汰阈值。
怎么调lfu-decay-time才有效?
调小它,让冷数据更快“失权”。但不能拍脑袋设成1秒——衰减过猛会误伤真实热点(比如用户连续刷3次同一商品页,间隔刚好卡在两次衰减之间,计数器被清零)。实操建议如下:
- 先用
INFO memory确认当前确实在用LFU策略(看maxmemory_policy字段是否含lfu) - 观察业务低峰期时长:如果夜间2点到6点几乎无请求,可将
lfu-decay-time设为300(5分钟),比默认快12倍,又留出缓冲余量 - 线上调整用命令:
CONFIG SET lfu-decay-time 300,无需重启;改配置文件则加一行lfu-decay-time 300 - 调完立刻用
OBJECT FREQ your:hot:key对比几个典型Key的频次变化,验证衰减是否生效
为什么不能只靠调参?还得配合TTL和结构优化
lfu-decay-time只是加速“计数器归零”,但若Key本身没设过期时间(EXPIRE),它仍会永远留在LFU候选池里——哪怕频次已归零,只要内存够,Redis就不淘汰它。更麻烦的是,大Key(如一个存了50万条评论的Hash)即使频次低,其内存占用也远超小Key,单靠LFU很难挤掉它。
- 对明确有生命周期的数据(如订单缓存、活动页配置),必须显式设置
EXPIRE,别依赖LFU“等它变冷” - 用
redis-cli --bigkeys定期扫出大Key,拆分或压缩(比如把单个Hash按天分片为order:20260401:{id}) - 检查
hash-max-listpack-entries等编码阈值,避免小Hash意外退化为高开销的hashtable,放大LFU管理成本
容易忽略的陷阱:LFU在AOF/RDB重载后计数器归零
Redis重启或从RDB/AOF恢复时,所有LFU频次计数器都会重置为0——这意味着历史热度完全丢失,刚启动那会儿,所有Key看起来都一样“冷”,淘汰逻辑近乎随机。如果你依赖LFU做长期热点识别,这个特性就是硬伤。
- 不要把LFU当“永久热度档案”,它只反映最近一段时间的访问分布
- 对真正关键的长期热点(如首页Banner配置),用
PERSIST移除过期时间 +allkeys-lru兜底,比强求LFU更稳 - 监控
evicted_keys指标突增,结合lfu-decay-time调整节奏,避免刚重启就因误淘汰导致大量回源


















