lfu不是简单计数,而是概率增长+时间衰减的复合机制:object freq返回8位对数频次(0–255),由lru字段高16位(ldt)和低8位(logc)组成;访问时按概率更新logc,避免溢出与高开销;需配置volatile-lfu或allkeys-lfu才生效,且依赖maxmemory触发淘汰。

LFU不是简单计数,而是概率增长+时间衰减的复合机制
Redis的OBJECT FREQ返回值不是访问次数,而是8位对数频次(0–255),它由两部分组成:lru字段的高16位存最后一次衰减时间(ldt),低8位存对数计数器(logc)。每次访问key时,并非直接+1,而是按概率决定是否更新——访问越频繁,增长越慢;刚被访问的key反而更容易涨分。这避免了计数器快速溢出,也降低了高频key的更新开销。
常见错误是看到OBJECT FREQ mykey返回0就认为没被统计,其实可能是:该key刚写入还没触发首次访问更新;或当前策略仍是allkeys-lru,LFU根本未启用。
- 必须先确认
CONFIG GET maxmemory-policy返回的是volatile-lfu或allkeys-lfu -
OBJECT FREQ只在key被访问后才可能更新,冷key或新key返回0属正常 - 不要用
OBJECT FREQ做精确计数,只适合横向比较热度高低
lfu-log-factor和lfu-decay-time直接影响淘汰行为
这两个参数不调,LFU很容易“失灵”:默认lfu-log-factor 10在低频场景下增长太猛,而lfu-decay-time 1(分钟)又让老热点衰减过快,结果就是冷热混杂、误删真热点。
比如突发流量打进来,新key频次涨得快但衰减也快;而一个稳定高频key,如果lfu-decay-time设得太小(如5),几分钟后计数器就被大幅拉低,可能被当成冷数据淘汰。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
-
lfu-log-factor越小,低频key增长越快(适合冷启动期),但高频key区分度下降 -
lfu-decay-time越大,历史热度保留越久(适合长周期热点),但新热点上位变慢 - 生产环境建议从
lfu-log-factor 5+lfu-decay-time 60起步,再根据OBJECT FREQ分布和命中率调整
LFU淘汰真正生效的前提是内存真的满了
很多人配置了allkeys-lfu却观察不到淘汰效果,是因为maxmemory没设或设得太高,Redis压根没触发淘汰逻辑。LFU不是后台常驻扫描机制,它只在写操作导致内存超限时才启动采样+淘汰流程。
验证方式很简单:用redis-cli --bigkeys看当前内存分布,再手动执行CONFIG SET maxmemory 100mb(远低于实际使用量),然后持续SET大量新key,观察INFO memory里的evicted_keys是否递增。
- 没设
maxmemory或设为0 → 永远不会淘汰 - 设了
maxmemory但当前used_memory远低于阈值 → LFU不工作 -
evicted_keys为0且内存充足 → 不代表LFU失效,只是没到触发点
LFU和LRU不是互斥,而是可共存于同一淘汰决策中
当多个key的OBJECT FREQ相同时,Redis会 fallback 到LRU逻辑:比较它们的最后访问时间(即lru字段高16位推导出的时间戳),淘汰更久未访问的那个。这是为了打破频率平局,避免“同频key无限堆积”。
这意味着你不能只盯着OBJECT FREQ判断谁该被淘汰——哪怕A的freq=12、B的freq=11,但如果B最近被访问过而A是3小时前访问的,在淘汰池里B反而更安全。
- LFU主排序依据是频次,LRU是次级兜底规则
- 采样阶段仍依赖
maxmemory-samples(默认5),值太小会导致采样偏差,影响淘汰公平性 - 真实淘汰发生在写操作期间,不是定时任务,所以压力突增时可能集中淘汰一批key
OBJECT FREQ的对数值映射回业务语义——比如“freq=200”到底对应每秒几次访问,这需要结合你的流量模型和衰减周期反推,而不是查文档就能得出。










