缓存是一个计算机思维,对于重复的计算,缓存其结果,下次再算这个任务的时候,不去真正的计算,而是直接返回结果,能加快处理速度。当然有些会随时间改变的东西,缓存会失效,得重新计算。

一、缓存淘汰算法定义

缓存算法是指令的一个明细表,用于决定缓存系统中哪些数据应该被删去。

常见类型包括LFU、LRU、ARC、FIFO、MRU。

二、最不经常使用算法(LFU-Least Frequently Used)

这个缓存算法使用一个计数器来记录条目被访问的频率。通过使用LFU缓存算法,最低访问数的条目首先被移除。这个方法并不经常使用,因为它无法对一个拥有最初高访问率之后长时间没有被访问的条目缓存负责。


三、最近最少使用算法(LRU-Least Recently Used

这个缓存算法将最近使用的条目存放到靠近缓存顶部的位置。当一个新条目被访问时,LRU将它放置到缓存的顶部。当缓存达到极限时,较早之前访问的条目将从缓存底部开始被移除。这里会使用到昂贵的算法,而且它需要记录“年龄位”来精确显示条目是何时被访问的。此外,当一个LRU缓存算法删除某个条目后,“年龄位”将随其他条目发生改变。

算法有两种策略(均以队列的方式实现),一种是不调整的,另外一种是随时进行调整的,即缓存命中后,将这个数据缓存项移到LRU队列的最前端。

java中利用LinkedHashMap来实现LRU算法,需要覆写其中的removeEldestEntry(Map.Entry)方法即可。如果去看LinkedHashMap的源码可知,LRU算法是通过双向链表来实现,当某个位置被命中,通过调整链表的指向将该位置调整到头位置,新加入的内容直接放在链表头,如此一来,最近被命中的内容就向链表头移动,需要替换时,链表最后的位置就是最近最少使用的位置。

LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展。

//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor);this.accessOrder = accessOrder;
}//LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据
//我们要做的就是重写这个方法,当满足一定条件时删除老数据
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {return false;//return size() > MAX_CACHE_SIZE;   (改为这个)}

四、自适应缓存替换算法(ARC-Adaptive Replacement Cache)

在IBM Almaden研究中心开发,这个缓存算法同时跟踪记录LFU和LRU,以及驱逐缓存条目,来获得可用缓存的最佳使用。

有人说是介于 LRU 和 LFU 之间,为了提高效果,是由2个 LRU 组成,第一个,也就是 L1,包含的条目是最近只被使用过一次的,而第二个 LRU,也就是 L2,包含的是最近被使用过两次的条目。因此, L1 放的是新的对象,而 L2 放的是常用的对象。所以,别人才会认为是介于 LRU 和 LFU 之间的,不过没关系,我不介意。

被认为是性能最好的缓存算法之一,能够自调,并且是低负载的。也保存着历史对象,这样,就可以记住那些被移除的对象,同时,也可以看到被移除的对象是否可以留下,取而代之的是踢走别的对象。他的记忆力很差,但是很快,适用性也强。

五、先进先出算法(FIFO-First in First out)

FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

六、最近最常使用算法(MRU-Most Recently Used)

这个缓存算法最先移除最近最常使用的条目。一个MRU算法擅长处理一个条目越久,越容易被访问的情况。

和 LRU 是对应的。会移除最近最多被使用的对象,你一定会问我为什么。好吧,让我告诉你,当一次访问过来的时候,有些事情是无法预测的,并且在缓存系统中找出最少最近使用的对象是一项时间复杂度非常高的运算,这就是为什么我是最好的选择。

我是数据库内存缓存中是多么的常见!每当一次缓存记录的使用,我会把它放到栈的顶端。当栈满了的时候,你猜怎么着?我会把栈顶的对象给换成新进来的对象!

七、Redis中使用的缓存总结

Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:

  • noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
  • allkeys-lru:在主键空间中,优先移除最近未使用的key。
  • volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
  • allkeys-random:在主键空间中,随机移除某个key。
  • volatile-random:在设置了过期时间的键空间中,随机移除某个key。
  • volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

我的微信公众号:架构真经(id:gentoo666),分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。每日更新哦!

参考资料:

  1. https://blog.csdn.net/youanyyou/article/details/78989956
  2. https://www.cnblogs.com/james111/p/7125353.html
  3. https://blog.csdn.net/w15249243295/article/details/52446845
  4. https://www.cnblogs.com/losing-1216/p/4953663.html

算法高级(11)-缓存淘汰算法研究相关推荐

  1. 06 | 链表(上):如何实现LRU缓存淘汰算法?

    缓存 作用 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存.数据库缓存.浏览器缓存等等. 淘汰策略 常见的策略有三种:先进先出策略 FIFO(F ...

  2. 看动画轻松理解「链表」实现「 LRU 缓存淘汰算法」

    作者 | 吴至波 责编 | 胡巍巍 快速挑战Python全栈工程师: https://edu.csdn.net/topic/python115?utm_source=csdn_bw 前几节学习了「链表 ...

  3. 缓存淘汰算法--LRU算法

    缓存淘汰算法--LRU算法 参考: https://www.cnblogs.com/dailidong/p/7571178.html https://blog.csdn.net/wangxilong1 ...

  4. 看动画轻松理解「链表」实现「LRU缓存淘汰算法」

    作者 | 程序员小吴,哈工大学渣,目前正在学算法,开源项目 「 LeetCodeAnimation 」5500star,GitHub Trending 榜连续一月第一. 本文为 AI科技大本营投稿文章 ...

  5. 算法必知 --- LRU缓存淘汰算法

    作者:_code_x 链接:https://www.jianshu.com/p/b7fed77324b9 写在前 就是一种缓存淘汰策略. 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾 ...

  6. 数据结构与算法 / LRU 缓存淘汰算法

    一.诞生原因 缓存是一种提供数据读取性能的技术,在硬件设计.软件开发中有广泛的应用,比如常见的 CPU 缓存,DB 缓存和浏览器缓存等.但是缓存的大小是有限的,需要一定的机制判断哪些数据需要淘汰,即: ...

  7. mysql缓存淘汰机制_聊聊缓存淘汰算法-LRU 实现原理

    前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来.缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据.常用淘 ...

  8. leetcode刷题:LRU缓存淘汰算法

    题目: 分析: 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置.但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用.那么, ...

  9. 看动画理解「链表」实现LRU缓存淘汰算法

    前几节学习了「链表」.「时间与空间复杂度」的概念,本节将结合「循环链表」.「双向链表」与 「用空间换时间的设计思想」来设计一个很有意思的缓存淘汰策略:LRU缓存淘汰算法. 循环链表的概念 如上图所示: ...

最新文章

  1. MapReduce编程实战之“调试”
  2. 【Scratch】青少年蓝桥杯_每日一题_6.01_画春花
  3. 关于windows内存泄露思考
  4. 开发常见单词Java
  5. 大牛书单 | 读懂5G,改变社会
  6. CPU占用率过高和OOM场景下如何排查问题
  7. linux下的C语言开发(gdb调试)
  8. caffe上手:修改已训练好的网络并训练模型
  9. 4r照片尺寸是多大_4寸照片尺寸多少厘米 多少像素
  10. Html 使 tbody加上滚动条
  11. 万洲金业:白银继续走高,预期缓慢冲高
  12. C语言基础之统计数字
  13. 【2023.3.18 美团校招】
  14. Appium自动化测试元素定位方式
  15. JS获取当前时间的前一个小时及格式化时间
  16. 毫米波雷达 3发4收 阵列信号回波模拟(基于信号的延时来建模)以及DOA和MVDR方法测角 (二)
  17. 未来的计算机事业作文600字,模块计算机考试的感想
  18. 【妇女节特辑】闪耀的工程师女性们
  19. 按颜色分类:黄色系(Yellow)
  20. KOReader开源PDF支持多平台

热门文章

  1. Extjs DateField onchange
  2. Log4j2使用总结
  3. 第十六章 复杂的抽像类结构
  4. string replaceAll
  5. 宅男程序员给老婆的计算机课程之4:SQL vs NoSQL
  6. WPF Splash Screen 和启动速度相关资料
  7. [我的成长:8期]一晃又半年了
  8. [MySQL优化案例]系列 -- DISABLE/ENABLE KEYS的作用
  9. leetcode100. 相同的树
  10. Redis常见面试题6 -- 持久化方式之AOF以及混合模式