前言
缓存淘汰算法是指:在有限容量的 list 中,空间被占满后要存入新的 item 时,决定出那个数据应该被剔除剔除的一类算法。
其核心是为了计算出哪个 item 应该被剔除,也就是淘汰机制。
介绍
LRU (Least Recently Used / 最近最少使用)
淘汰最久没有用过的元素。
基本思想
如果数据过去被访问多次,那么将来被访问的频率也更高。
存在的问题
偶发性的、周期性的批量查询操作(包含冷数据)会淘汰掉大量的热点数据,导致 LRU 命中率急剧下降,缓存污染情况比较严重。
LFU (Least Frequently Used / 最不经常使用)
淘汰访问频率最低的元素。
注意 LFU 和 LRU 的区别,LRU 的淘汰规则是基于访问时间,而 LFU 是基于访问次数。
基本思想
如果数据最近被访问过,那么将来被访问的几率也更高。
存在的问题:
- 最近加入的数据总是易于被剔除(缓存末端抖动),因为他起始的频率很低。它无法对一个拥有最初高访问率之后长时间没有被访问的条目缓存负责。
- 为了避免早期的热点数据一直占据缓存,即LFU算法也需有一些访问时间模式的特性。
但是,如果频率的时间度量是 1 小时(数据根据最近一小时内的访问次数排序),则平均每小时访问 1000 次的数据可能会比前一个小时内访问次数为 1001 的数据更优先剔除掉。
一般情况下,LFU 效率要优于 LRU,且能够避免周期性或者偶发性的操作导致缓存命中率下降的问题,但 LFU 需要记录数据的历史访问记录,一旦数据访问模式改变,LFU 需要更长时间来适用新的访问模式,即 LFU 存在历史数据影响将来数据的缓存污染
问题。
LFU 使用计数器来记录条目被访问的频率,通过使用 LFU 缓存算法,最低访问次数的条目首先被移除,此方法并不经常使用,因为它无法对一个拥有最初高访问率之后长时间没有被访问的条目缓存负责。
总结
由于两种算法的各自特点及缺点,所以在行业生产线上通常会联合两者使用。
我们可以在 LRU 的实现基础上稍作衍生,可以采用队列分级的思想。
例如 Oracle 利用两个队列维护访问的数据元素,按被访问的频率的维度把元素分别搁在热端与冷端队列;而在同一个队列内,最后访问时间越久的元素会越被排在队列尾,实现细节参考 详解Oracle数据库LRU算法:LRU链、脏块与脏LRU链。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。