
正文
两种常见的缓存淘汰算法LFU&LRU
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
1. LFU
1.1. 原理
LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。
1.2. 实现
LFU的每个数据块都有一个引用计数,所有数据块按照引用计数排序,具有相同引用计数的数据块则按照时间排序。
具体实现如下:
1. 新加入数据插入到队列尾部(因为引用计数为1);
2. 队列中的数据被访问后,引用计数增加,队列重新排序;
3. 当需要淘汰数据时,将已经排序的列表最后的数据块删除。
1.3. 分析
l 命中率
一般情况下,LFU效率要优于LRU,且能够避免周期性或者偶发性的操作导致缓存命中率下降的问题。但LFU需要记录数据的历史访问记录,一旦数据访问模式改变,LFU需要更长时间来适用新的访问模式,即:LFU存在历史数据影响将来数据的“缓存污染”效用。
l 复杂度
需要维护一个队列记录所有数据的访问记录,每个数据都需要维护引用计数。
l 代价
需要记录所有数据的访问记录,内存消耗较高;需要基于引用计数排序,性能消耗较高。
2. LRU
2.1. 原理
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
2.2. 实现
最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:

1. 新数据插入到链表头部;
2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
3. 当链表满的时候,将链表尾部的数据丢弃。
2.3. 分析
【命中率】
当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。
【复杂度】
实现简单。
【代价】
命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。
3. LRU-K
3.1. 原理
LRU-K中的K代表最近使用的次数,因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。
3.2. 实现
相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。只有当数据的访问次数达到K次的时候,才将数据放入缓存。当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。详细实现如下:

1. 数据第一次被访问,加入到访问历史列表;
2. 如果数据在访问历史列表里后没有达到K次访问,则按照一定规则(FIFO,LRU)淘汰;
3. 当访问历史队列中的数据访问次数达到K次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序;
4. 缓存数据队列中被再次访问后,重新排序;
5. 需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。
LRU-K具有LRU的优点,同时能够避免LRU的缺点,实际应用中LRU-2是综合各种因素后最优的选择,LRU-3或者更大的K值命中率会高,但适应性差,需要大量的数据访问才能将历史访问记录清除掉。
3.3. 分析
【命中率】
LRU-K降低了“缓存污染”带来的问题,命中率比LRU要高。
【复杂度】
LRU-K队列是一个优先级队列,算法复杂度和代价比较高。
【代价】
由于LRU-K还需要记录那些被访问过、但还没有放入缓存的对象,因此内存消耗会比LRU要多;当数据量很大的时候,内存消耗会比较可观。
LRU-K需要基于时间进行排序(可以需要淘汰时再排序,也可以即时排序),CPU消耗比LRU要高。
两种常见的缓存淘汰算法LFU&LRU的更多相关文章- 两种缓存淘汰算法LFU&;LRU
LRU全称是Least Recently Used,即最近最久未使用的意思. LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已 ...
- 缓存淘汰算法之LRU
1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”. ...
- 缓存淘汰算法之LRU实现
Java中最简单的LRU算法实现,就是利用 LinkedHashMap,覆写其中的removeEldestEntry(Map.Entry)方法即可 如果你去看LinkedHashMap的源码可知,LR ...
- 图解缓存淘汰算法二之LFU
1.概念分析 LFU(Least Frequently Used)即最近最不常用.从名字上来分析,这是一个基于访问频率的算法.与LRU不同,LRU是基于时间的,会将时间上最不常访问的数据淘汰;LFU为 ...
- 昨天面试被问到的 缓存淘汰算法FIFO、LRU、LFU及Java实现
缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是, ...
- 04 | 链表(上):如何实现LRU缓存淘汰算法?
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
- 数据结构与算法之美 06 | 链表(上)-如何实现LRU缓存淘汰算法
常见的缓存淘汰策略: 先进先出 FIFO 最少使用LFU(Least Frequently Used) 最近最少使用 LRU(Least Recently Used) 链表定义: 链表也是线性表的一种 ...
- 链表:如何实现LRU缓存淘汰算法?
缓存淘汰策略: FIFO:先入先出策略 LFU:最少使用策略 LRU:最近最少使用策略 链表的数据结构: 可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可 ...
- 《数据结构与算法之美》 <;04>;链表(上):如何实现LRU缓存淘汰算法?
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
随机推荐- Hibernate SQL实际sql语句监控- p6spy+hibernate+proxool 设置
由于ORM工具的缘故,我们调试程序的时候远没有直接在程序里直接写个string的SQL简单,想当年查个sql是有多么的幸福,一行sql = "select * from ..."找 ...
- 如何利用jQuery进行简单表单验证
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name=&qu ...
- Java异常之try,catch,finally,throw,throws
Java异常之try,catch,finally,throw,throws 你能区分异常和错误吗? 我们每天上班,正常情况下可能30分钟就能到达.但是由于车多,人多,道路拥挤,致使我们要花费更多地时间 ...
- 英特尔&#174; 硬件加速执行管理器安装指南 — Microsoft Windows*
介绍 本文将指导您安装英特尔® 硬件加速执行管理器(英特尔® HAXM),这是一款可以使用英特尔® 虚拟化技术(VT)加快 Android* 开发速度的硬件辅助虚拟化引擎(管理程序). 前提条件 英特 ...
- DisplayContent、StackBox、TaskStack笔记
文章仅零散记录自己的一点理解,仅供自己參考. 每一个显示设备,都有一个Display对象,DisplayManagerService专门管理这些Display. 1.DisplayContent() ...
- js Date() 浏览器兼容问题解决
一般 直接new Date() 是不会出现兼容性问题的,而 new Date(datetimeformatstring) 常常会出现浏览器兼容性问题,为什么,datetimeformatstring中 ...
- JS 存储
1. 描述cookie ,sessionStorage 和 localStorage 的区别? cookie : 本身用于客户端和服务器端通信, 但是有本身存储的功能,就被‘借用’ 使用documen ...
- Eclipse中项目不会自动编译问题的坑和注意点
最近接受了几个又小有老的项目,用eclipse反而比idea方便,但是好长时间不用eclipse了,还有有些问题的! 主要是碰到了classnotfound这个难缠的问题:这里记录一下几个坑,避免以后 ...
- c++引用(修改引用的值)
当我们希望修改某个函数的返回值时,通常我们会返回这个值的引用(因为函数返回值其实是返回那个值得一份拷贝而已,所以想要修改必须使用引用): .h文件 #pragma once #include < ...
- bzoj 3931: [CQOI2015]网络吞吐量 -- 最短路+网络流
3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec Memory Limit: 512 MB Description 路由是指通过计算机网络把信息从源地址传输到目的地址 ...
LRU全称是Least Recently Used,即最近最久未使用的意思. LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已 ...
1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”. ...
Java中最简单的LRU算法实现,就是利用 LinkedHashMap,覆写其中的removeEldestEntry(Map.Entry)方法即可 如果你去看LinkedHashMap的源码可知,LR ...
1.概念分析 LFU(Least Frequently Used)即最近最不常用.从名字上来分析,这是一个基于访问频率的算法.与LRU不同,LRU是基于时间的,会将时间上最不常访问的数据淘汰;LFU为 ...
缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是, ...
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
常见的缓存淘汰策略: 先进先出 FIFO 最少使用LFU(Least Frequently Used) 最近最少使用 LRU(Least Recently Used) 链表定义: 链表也是线性表的一种 ...
缓存淘汰策略: FIFO:先入先出策略 LFU:最少使用策略 LRU:最近最少使用策略 链表的数据结构: 可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可 ...
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
- Hibernate SQL实际sql语句监控- p6spy+hibernate+proxool 设置
由于ORM工具的缘故,我们调试程序的时候远没有直接在程序里直接写个string的SQL简单,想当年查个sql是有多么的幸福,一行sql = "select * from ..."找 ...
- 如何利用jQuery进行简单表单验证
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name=&qu ...
- Java异常之try,catch,finally,throw,throws
Java异常之try,catch,finally,throw,throws 你能区分异常和错误吗? 我们每天上班,正常情况下可能30分钟就能到达.但是由于车多,人多,道路拥挤,致使我们要花费更多地时间 ...
- 英特尔&#174; 硬件加速执行管理器安装指南 — Microsoft Windows*
介绍 本文将指导您安装英特尔® 硬件加速执行管理器(英特尔® HAXM),这是一款可以使用英特尔® 虚拟化技术(VT)加快 Android* 开发速度的硬件辅助虚拟化引擎(管理程序). 前提条件 英特 ...
- DisplayContent、StackBox、TaskStack笔记
文章仅零散记录自己的一点理解,仅供自己參考. 每一个显示设备,都有一个Display对象,DisplayManagerService专门管理这些Display. 1.DisplayContent() ...
- js Date() 浏览器兼容问题解决
一般 直接new Date() 是不会出现兼容性问题的,而 new Date(datetimeformatstring) 常常会出现浏览器兼容性问题,为什么,datetimeformatstring中 ...
- JS 存储
1. 描述cookie ,sessionStorage 和 localStorage 的区别? cookie : 本身用于客户端和服务器端通信, 但是有本身存储的功能,就被‘借用’ 使用documen ...
- Eclipse中项目不会自动编译问题的坑和注意点
最近接受了几个又小有老的项目,用eclipse反而比idea方便,但是好长时间不用eclipse了,还有有些问题的! 主要是碰到了classnotfound这个难缠的问题:这里记录一下几个坑,避免以后 ...
- c++引用(修改引用的值)
当我们希望修改某个函数的返回值时,通常我们会返回这个值的引用(因为函数返回值其实是返回那个值得一份拷贝而已,所以想要修改必须使用引用): .h文件 #pragma once #include < ...
- bzoj 3931: [CQOI2015]网络吞吐量 -- 最短路+网络流
3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec Memory Limit: 512 MB Description 路由是指通过计算机网络把信息从源地址传输到目的地址 ...







