LFU不是替代LRU,而是补足其时间维度盲区;它通过概率计数器与衰减机制识别真实热点,解决LRU无法区分“短期冷数据”和“长期高频但偶有空闲”的问题。

LFU不是为了“替代LRU”,而是补足时间维度盲区
LRU在Redis里实际是近似算法,只记录最后一次访问时间戳(lru字段),它无法区分“刚被访问过但长期冷数据”和“高频访问但最近没动的真热点”。比如一个用户画像键每小时被读10次,连续跑了3天,第4天凌晨没被访问——LRU会把它当作“最久未用”直接淘汰,而它其实是业务核心数据。LFU引入的根本动因,就是解决这类**频率感知缺失**问题。
allkeys-lfu 和 volatile-lfu 的适用边界很明确
选allkeys-lfu还是volatile-lfu,不取决于“要不要LFU”,而取决于你的键有没有统一设TTL:
- 如果所有缓存都带
EXPIRE,比如会话、临时token、活动页数据,用volatile-lfu更安全——避免误删永久配置类键 - 如果混用永久键(如全局配置、用户基础信息)和临时键,必须用
allkeys-lfu,否则永久键永远不会参与淘汰,内存迟早撑爆 -
volatile-lfu在TTL设置不规范时风险很高:比如有人忘了给键设过期时间,它就彻底“免疫”淘汰
LFU的计数器不是简单累加,衰减机制才是关键
Redis复用lru字段的24位,高16位存上次衰减时间(ldt),低8位存对数计数器(logc)。这意味着:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 计数器增长是概率性的:访问越频繁,每次+1的概率越低,防止
logc很快到255失去区分度 - 衰减由
lfu-log-factor控制(默认10):值越大,旧访问权重衰减越慢;值太小(如1)会导致短期突发流量把冷数据“刷热”,误保 - 衰减触发时机是惰性的:只有当某个键被访问,且距上次衰减超过
lfu-decay-time(默认1分钟)时才执行
LFU在真实业务中容易被低估的两个成本
启用LFU不是开个开关就完事,它有隐性代价:
- 内存开销没变,但CPU消耗上升:每次访问都要做概率计算+条件衰减,比LRU单纯更新时间戳贵不少,在QPS超5万的实例上可观测到CPU使用率+3%~5%
- 监控难度陡增:
INFO stats里的evicted_keys不告诉你为什么被淘汰,得配合MEMORY USAGE和OBJECT FREQ手动采样分析,否则根本不知道是衰减不合理,还是业务访问模式突变
真正难的不是配maxmemory-policy,而是验证你选的lfu-log-factor是否匹配业务访问周期——这个参数调不好,LFU可能比LRU还容易误杀热点。

















