知识卡片

FIFO-LRU-LFU三种淘汰策略的递进与各自局限

结构图卡

内容

缓存容量有限,必须淘汰”低价值”数据,而这个价值判断必须与具体业务无关, 只能依赖通用统计信息(进入时间、使用次数、最近使用时间)。三种基础策略 依次针对前一种的短板改进:FIFO只看”进入时间”、淘汰最早进入的数据,实现 最简单,但完全不管数据是否常被访问,频繁使用的数据反而可能因为进入得早 而被优先清理,命中率通常不理想。LRU看”最近使用时间”、淘汰最久未访问的 数据(用HashMap+LinkedList实现,命中时把节点移到链表头部,淘汰时清理 链表尾部),能捕捉到”最近很热”的数据,比FIFO合理得多,但有个反直觉的 盲点:一个长期高频访问的热点数据,只要中间恰好有一段时间没被访问,就有 被LRU误杀的风险——LRU只看”最近一次”,不看”历史总频率”。LFU看”访问次数”、 淘汰计数器最小的数据,能解决”偶尔断档的热点被误杀”问题,但引入了新代价: 每个数据都要维护一个计数器且每次访问都要更新,开销不小;而且很难处理 “热度随时间衰减”——曾经频繁访问但现在已经不需要的数据,计数器居高不下, 很难被自动清理出去。三者构成一条清晰的”精度提升、代价也提升”的链条。

结构图

flowchart LR
    FIFO["FIFO: 只看进入时间<br/>简单, 但热数据可能被误杀"] -->|改进为看访问时间| LRU["LRU: 看最近访问时间<br/>捕捉近期热点, 但断档热点易误杀"]
    LRU -->|改进为看访问频率| LFU["LFU: 看历史访问总次数<br/>解决断档问题, 但维护开销大且难衰减"]

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第4章"透明多级分流系统" 4.6.1节"缓存属性"(源文件:_epub-src对应OEBPS/Text/chapter54.xhtml) - 结论依据:原文依次说明FIFO"越是频繁被用到的数据,往往会越早存入缓存" 导致命中率低、LRU可能错误淘汰"因某种原因未被访问过"的热点数据、LFU 需要为每个数据维护计数器且不便处理随时间变化的热度,直接支撑本卡片 的递进结构梳理。 - 原始内容:LFU可以解决上面LRU中热点数据间隔一段时间不访问就被淘汰的 问题,但同时它又引入了两个新的问题。第一个问题是需要对每个缓存的数据 专门维护一个计数器……另一个问题是不便于处理随时间变化的热度变化。