缓存淘汰算法-LRU

news2025/1/20 15:48:42

目录

前言

一、LRU 算法

二、LRU 算法图解

三、LRU 算法实现

四、LRU 算法分析

五、LRU 算法改进方案


前言

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


一、LRU 算法

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:

1. 新数据插入到链表头部;

2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;

3. 当链表满的时候,将链表尾部的数据丢弃。

二、LRU 算法图解

1.初始化一个大小为 n 的列表

2.访问一个数据且该数据存在于缓存空间中,返回该数据对应值并将该节点移动到列表头节点, 其余节点位置不变。比如访问 key=C

 

3.插入一个 key=G 节点,直接将数据添加到头结点

4. 假设列表已满,这时再插入一个 key=H 节点,则先删除F节点,在将H节点添加到头结点 

 

这里总结一下 LRU 算法的具体步骤:

  • 新数据直接插入到列表头部
  • 缓存数据被命中,将数据移动到列表头部
  • 缓存已满的时候,移除列表尾部数据。

三、LRU 算法实现

上面例子中可以看到,LRU 算法需要添加头节点,删除尾结点。而链表添加节点/删除节点时间复杂度 O(1),非常适合当做存储缓存数据容器。但是不能使用普通的单向链表,单向链表有几点劣势:

  1. 每次获取任意节点数据,都需要从头节点遍历下去,这就导致获取节点复杂度为 O(N)。
  2. 移动中间节点到头结点,我们需要知道中间节点前一个节点的信息,单向链表就不得不再次遍历获取信息。

针对以上问题,可以结合其他数据结构解决。

使用散列表存储节点,获取节点的复杂度将会降低为 O(1)。节点移动问题可以在节点中再增加前驱指针,记录上一个节点信息,这样链表就从单向链表变成了双向链表。

综上使用双向链表加散列表结合体,数据结构如图所示:

在双向链表中特意增加两个『哨兵』节点,不用来存储任何数据。使用哨兵节点,增加/删除节点的时候就可以不用考虑边界节点不存在的情况,简化编程难度,降低代码复杂度。

四、LRU 算法分析

缓存命中率是缓存系统的非常重要指标,如果缓存系统的缓存命中率过低,将会导致查询回流到数据库,导致数据库的压力升高。

结合以上分析 LRU 算法优缺点。

LRU 算法优势在于算法实现难度不大,对于热点数据, LRU 效率会很好。

LRU 算法劣势在于对于偶发的批量操作,比如说批量查询历史数据,就有可能使缓存中热门数据被这些历史数据替换,造成缓存污染,导致缓存命中率下降,减慢了正常数据查询。

五、LRU 算法改进方案

以下方案来源于 MySQL InnoDB LRU 改进算法

将链表拆分成两部分,分为热数据区,与冷数据区,如图所示。

改进之后算法流程将会变成下面的一样:

  1. 访问数据如果位于热数据区,与之前 LRU 算法一样,移动到热数据区的头结点。
  2. 插入数据时,若缓存已满,淘汰尾结点的数据。然后将数据插入冷数据区的头结点。
  3. 处于冷数据区的数据每次被访问需要做如下判断:
  4. 若该数据已在缓存中超过指定时间,比如说 1 s,则移动到热数据区的头结点。
  5. 若该数据存在在时间小于指定的时间,则位置保持不变。

对于偶发的批量查询,数据仅仅只会落入冷数据区,然后很快就会被淘汰出去。热门数据区的数据将不会受到影响,这样就解决了 LRU 算法缓存命中率下降的问题。

六、Redis LRU 算法

redis中每一个value都可以理解为是一个RedisObject,结构体RedisObject定义了5个属性:type、enconding、lru、refcount和*prt,如下图

Redis对每个KV对中的V,会使用个redisObject结构体保存指向V的指针。那redisObject除记录值的指针,还会使用24 bits保存LRU时钟信息,对应的是lru成员变量。这样,每个KV对都会把它最近一次被访问的时间戳,记录在lru变量。

Redis 在每个数据对象 RedisObject 中存放 lru 字段,表示该数据最近一次访问的时间戳,以后做数据淘汰时用该字段作为比较依据。

当执行数据淘汰时, 首次 执行将按以下步骤选择数据:

1、随机 选出 N (maxmemory-samples)个数据,把它们作为一个候选集合;

2、比较这 N 个数据的 lru 字段,把 lru 字段值最小的数据淘汰出去;

以后 再次 进行数据淘汰时,将以 第一次淘汰时创建的候选集合中最小的 lru 值 minLruInSet 为基准,挑选 lru 字段值 小于 minLruInSet 的数据并放入到集合中,当候选数据集中的数据个数再次达到 maxmemory-samples 时,Redis 就把候选集合中 lru 字段值最小的数据淘汰出去。

通过维护这个 lru 小值集合可以减小发生数据淘汰时对 redis 产生的性能影响,因为它不需要使用链表来保存所有的数据,也不存在数据的移动。

官网 表明在样本数 maxmemory-samples = 10 的情况下,Redis3.0 很接近真正的 LRU 实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/991434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IP175LLF基本参数和引脚图

特性 宽工作温度范围IP175LLF(0C至70C) IP175LLFI(-40C至85C)内置5个MAC和4个PHY 每个端口可配置为10base-t、100Base-TX 最多2K个MAC地址支持自极性10Mbps 汽车MDI-MDIX 支持1个MII/RMII端口Layer2-4多字段分类器 支持8-MultiField输入支持交通政策支持多字段过滤器 支…

【word技巧】如何在word文件中方框打对勾?

Word文件制作了调查问卷或者信息表之类的文件,总是少不了有需要打勾的选项,如果打印成了纸质文件打勾就简单了,但是在word文件中应该如何在方框中打√符号呢?今天分享三个方法。 方法一: 先输入一个大写的R&#xff…

MES生产管理系统的五个关键组件

MES管理系统在当今制造业中发挥着越来越重要的作用。它是一种先进的生产管理系统,旨在连接企业资源计划(ERP)系统和生产现场之间的信息桥梁。在本文中,我们将探讨在制造过程中实施MES管理系统时需要考虑的几个关键因素。 首先&…

【漏洞复现】金和OA C6任意文件读取漏洞

漏洞描述 金和OA协同办公管理系统C6软件共有20多个应用模块,160多个应用子模块,涉及的企业管理业务包括协同办公管理、人力资源管理、项目管理、客户关系管理、企业目标管理、费用管理等多个业务范围,从功能型的协同办公平台上升到管理型协同…

计算机脚本的概念,如何编写、使用脚本 (Script)?

一、脚本的概念和使用场景 在计算机领域的脚本,指的是使用一种特定的描述性语言,依据一定的格式编写的可执行文件脚本语言又被称为扩建的语言或者动态语言, 是一种编程语言, 用来控制软件应用程序, 脚本通常是以文本 (ASCⅡ) 保存, 只是在被调用时进行解…

AFL++模糊测试

一、AFL 这里我们主要使用AFL Fuzzing 测试IOT的二进制文件,当我们解压提取一个固件时,能够获得大量的IOT二进制应用 ,如果要进行漏洞挖掘则需要将二进制文件进行逆向分析,然后查找危险函数以及输入接口,对于一个大型的…

管理类联考——数学——汇总篇——知识点突破——数据分析——计数原理——排列组合——成双

🌊 配对问题的解题思路:配对问题主要以鞋子或者手套来作为命题对象,其核心在于成双不成双,对于成双问题,直接选取整双即可,对于不成双问题,要先取成双的,然后从每双中取单只即可。 …

计算机使用中常用截图与标注方法

一、截图常用方法 1.windows自带快捷键 Print Screen SysPq 截取全屏,可以粘到word文档中,可以粘贴到"画图"程序中,命名一个文件名,另存为图片,或.jpg后缀,或.png后缀 alt Print S…

掌动智能国产化测试工具的重要性与优势

在信息技术领域的快速发展下,对于软件和硬件产品的质量和性能要求也日益提高。同时针对信创要求,国产化测试工具在这个过程中发挥着重要的作用,不仅能够提升产品的可靠性和稳定性,还能够降低测试成本和提高测试效率。作为国内领先…

win10怎么禁止软件联网

有一些用户发现软件在联网的状态下会进行自动更新,想要禁止软件联网却不知道如何操作,这里小编就给大家详细介绍一下Win10禁止软件联网的方法,有需要的小伙伴快来和小编一起看一看了解一下吧。 Win10禁止软件联网的方法: 1、按下…

【校招VIP】测试算法考点之链表

考点介绍: 链表是一种逻辑简单的、实用的数据结构,几乎被所有程序设计语言支持。单链表的操作算法是笔试面试中较为常见的题目。 测试算法考点之链表-相关题目及解析内容可点击文章末尾链接查看! 一、考点题目 1.一个长度为n的单向链表&am…

智能离子风棒联网监控静电消除器的工作原理和特点

智能离子风棒联网监控静电消除器是一种应用了物联网技术的设备,用于监测和控制静电消除过程。下面是该设备的工作原理和特点: 工作原理: 1. 检测静电水平:智能离子风棒内置传感器,可以实时监测环境中的静电水平。 2.…

高等工程数学张韵华版第四章课后题答案

下面答案仅供参考! 章节目录 第4章 欧氏空间和二次型 4.1内积和欧氏空间 4.1.1内积的定义 4.1.2欧氏空间的性质 4.1.3 正交投影 4.1.4 施密特正交化 4.2 正交变换和对称变换 4.2.1 正交变换 4.2.2 正交矩阵 4.2.3 对称变换 4.2.4 对称矩阵 4.3 二…

12-JVM调优实战-2

上一篇:11-JVM调优实战-1 1.JVM运行情况预估 用 jstat gc -pid 命令可以计算出如下一些关键数据,有了这些数据就可以采用之前介绍过的优化思路,先给自己的系统设置一些初始性的JVM参数,比如堆内存大小,年轻代大小&a…

Springboot整合AOP实现日志的保存

1.定义注解 /*** 系统日志元注解*/ Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface LogFilter {String value() default "" ; } 2.编写切面的实现 Aspect Component public class LogAspect {private static final …

SW孤立基准面的方法

先把要单独显示的对象选择出来建立选择集, 然后框选所有基准面(过滤基准面),选择隐藏, 最后把选择集的打开。

【Mysql】Mysql获取排班时间段中的休息时间段方法

在MySQL中,可以使用自连接(self-join)来获取上一条记录的结束时间和下一条记录的开始时间,并将它们组合成一条记录。首先,需要为表创建一个包含记录ID和时间信息的临时表,然后使用自连接获取相邻记录的时间…

seata升级1.1.0后遇到io.seata.common.exception.ShouldNeverHappenException

我们这一节主要讲的是seata升级后的主要修改,至于seata的基本部署可以参考我之前的随笔。 一开始我在升级SpringBoot版本之后,seata就突然启动不起来了,报了下面的错: Caused by: io.seata.common.exception.ShouldNeverHappenExc…

将AI融入到SEO中—基于Python的实现思路

在当今数字化时代,搜索引擎优化(SEO)对于网站和在线业务的成功至关重要。然而,随着人工智能(AI)技术的迅猛发展,我们可以利用它来提升SEO策略并取得更好的效果。本文将介绍如何通过使用Python编…

浅谈多回路电表在荷兰光伏系统配电项目中的应用

1.背景信息 Background: 随着全球化石能源(石油,煤炭)越来越接近枯竭,污染日趋严重,气候日益变暖等问题,全球多个国家和地区相继出台了法规政策,推动了光伏产业的发展。但是现有的光…