【LRU】一文让你弄清 Redis LRU 页面置换算法

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 【LRU】一文让你弄清 Redis LRU 页面置换算法

Q:一天同事问,我放在 redis 中的 key,为什么有时候过一段时间数据就没有了,我并没有设置过期时间呀??😳😳

A:你的 redis 淘汰策略是什么样的,这个 key 可能是被 redis 自身的淘汰策略干掉了

一看 redis 的 config 文件 redis.conf

果然,你配置的是 maxmemory_policy allkey-lfu ,这个是 Redis 中的淘汰策略,是会从 redis 数据集中挑选使用频率最低的数据进行淘汰的

Q:不明觉厉,摸摸头👀👀

A:我给你简单说一下关于 redis 的淘汰策略吧

首先,redis 删除数据的策略目前来看有三种

  • 👀定时删除

见名知意,定时,自然就像我们定起床闹钟一样,此处是定一个删除 key 的闹钟,当我们对一个 key 设置过期时间的时候,会同时开启一个定时器,当时间到到的时候,就会删除这个 key

这种方式,需要我们额外开一个定时器,会消耗CPU资源

  • 👀惰性删除

惰性,一看就知道这种删除方式是被动的,若一个 key 过期了,redis 不会主动去删除他,而是当这个 key 再次被访问的时候,redis 看他有没有失效,若失效,则删除他

这种方式可以看出,如果一些过期的 key ,再没有被再次访问之前,就会一直存在内存中,非常浪费内存资源

  • 😁主动删除

顾名思义,这种方式是 redis 中会去设置各种策略,去按照不同的策略去删除一些不符合要求的数据,简单的,我们来看看 Redis 的淘汰策略,掌握主动权

Redis 的淘汰策略

可以看出 redis 的淘汰策略大体上有 5 种方式

  • LRU
  • LFU
  • RANDOM

会从数据集中随机选择数据进行删除,按照配置的策略不同 allkeys-random 则是将在所有数据集中进行随机 , volatile-random 是在已经设置了过期时间的数据中去随机淘汰

  • TTL

会从设置了过期时间的数据中,挑选要过期的数据进行淘汰

  • No-eviction (默认,不驱逐数据)

上述五种,看了后面三种都比较好理解,对于前面两种,我来详细给你说一下他的原理,便于你能够理解和记住,而不是去背诵他,面试的时候还可以手撸一下实现代码

前面两种方式,LRU 和 LFU 都是属于页面置换算法,其中还有一个最简单的页面置换算法是 FIFO,学过基本数据结构的对于 FIFO 先入先出的特性并不模式,因此就不在这里展开了,咱们本次主要聊聊 LRU ,很多时候很多同学还是不理解

LRU 的思想和实现

LRU 全称为:Least recently used

含义为:最近最少使用

思想是:如果数据最近被访问过,那么未来最近一段时间,这个数据未来被访问的几率也会更大

思想就是这么简单,不过他已经足够指导我们实践了

我们根据思想来分析一下 LRU 如何去实现它

首先,我们知道数据在内存中是用链表的方式来连接,此处我们可以使用双向链表

那么,对于链表来说,插入数据是很方便的,但是读取的数据的话,难道我们每一次都要去遍历一遍 key 吗?

自然不是,因此对于 LRU 中,还是用 hashmap 来存放 key 和链表上具体数据节点的关系

这样,当访问任何一个 key 的时候,就可以通过 hashmap 中取到节点,进而取到节点的值即可,这种方式的时间复杂度就可以从O(n) 降低到 O(1)

那么对于去实现 最近最少使用 的思想,那就是结合 hashmap 和双向链表来进行实现

  • 插入数据使用头插法,若访问到链表中的某个数据,则将该数据移动到链表头
  • 若插入数据时,链表容量已满,此时淘汰链表尾部的数据

✔举例时刻

举个例子,相信你就可以明白

例如,我们要插入这些数据 set(0,0),set(1,1),set(2,2),set(3,3),set(4,4),get(3) ,链表的容量为 3,来模拟一下 LRU 的处理过程

先插入 3 个数据到 链表中 0, 1, 2,

此处为了简单,咱们将 key 和 value 的值做成一样的

插入 3,

链表容量已满,删除链表尾的数据,这个时候,就已经是发生了缺页,需要对数据进行置换,淘汰链表尾,hashmap 中删除链表为对应的数据,新增 3 这个节点的数据到 hashmap 中

插入4,

链表容量已满,删除链表尾的数据,这个时候,就已经是发生了缺页,需要对数据进行置换,淘汰链表尾,hashmap 中删除链表为对应的数据,新增 4 这个节点的数据到 hashmap 中

获取 3,

由于链表中已经有 3 ,因此会将 3 移动到链表头

从上述演示中,我们可以看到关于 LRU 的关键逻辑

  1. 实现基本的链表
  2. 插入的数据时,如果链表已满,那么链表尾部的数据直接删掉,即淘汰
  3. 查询数据的时候,若数据已经存在于链表中,则将该节点移动到头节点上

那么在实现的时候,只需要实现基本的链表以及其对应的基础方法 (头插法,尾插法,移动节点,查询节点等) ,以及使用 hashmap 来记录链表中具体的 key 和具体的节点

思想,以及 LRU 中链表数据变动的过程明白了,写代码都是很简单的事情,感兴趣的 xdm 可以查看我的 code 地址:https://github.com/qingconglaixueit/my_lru_lfu/blob/main/my_lru/lru.go

实现结果

链接中的代码,可以看到 main.go 实现如下

咱们可以将数据修改成文中的例子,

运行 main.go 之后,可以看到结果如下:

红色部分,表示发生了缺页中断, 向链表中追加的 key 是 0,1,2,3,4,3

感兴趣的话,还是将 代码下载下来,自己跑一下,多多感受一下 LRU 的思想和流程,很容易就可以理解😁😁

总结

这下对于 Redis 的淘汰策略,心中有个数了吧

对于 LRU的具体实现方式相信你可以可以很容易的看明白的,实践起来吧,源码地址为:https://github.com/qingconglaixueit/my_lru_lfu

感谢阅读,欢迎交流,点个赞,关注一波 再走吧

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

文中提到的技术点,感兴趣的可以查看这些文章:

可以进入地址进行体验和学习:https://xxetb.xet.tech/s/3lucCI

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
16天前
|
存储 缓存 算法
LRU(Least Recently Used)算法原理
LRU(Least Recently Used)算法原理
12 0
|
2月前
|
算法
页面置换算法
页面置换算法
33 1
|
2月前
|
缓存 监控 算法
如何调整InnoDB的LRU算法以提高效率?
【5月更文挑战第14天】如何调整InnoDB的LRU算法以提高效率?
20 2
|
2月前
|
缓存 算法 Java
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
数据结构~缓存淘汰算法--LRU算法(Java的俩种实现方式,万字解析
|
2月前
|
缓存 算法 前端开发
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
|
5天前
|
机器学习/深度学习 自然语言处理 算法
m基于深度学习的OFDM+QPSK链路信道估计和均衡算法误码率matlab仿真,对比LS,MMSE及LMMSE传统算法
**摘要:** 升级版MATLAB仿真对比了深度学习与LS、MMSE、LMMSE的OFDM信道估计算法,新增自动样本生成、复杂度分析及抗频偏性能评估。深度学习在无线通信中,尤其在OFDM的信道估计问题上展现潜力,解决了传统方法的局限。程序涉及信道估计器设计,深度学习模型通过学习导频信息估计信道响应,适应频域变化。核心代码展示了信号处理流程,包括编码、调制、信道模拟、降噪、信道估计和解调。
26 8
|
7天前
|
算法
基于GA遗传优化的混合发电系统优化配置算法matlab仿真
**摘要:** 该研究利用遗传算法(GA)对混合发电系统进行优化配置,旨在最小化风能、太阳能及电池储能的成本并提升系统性能。MATLAB 2022a用于实现这一算法。仿真结果展示了一系列图表,包括总成本随代数变化、最佳适应度随代数变化,以及不同数据的分布情况,如负荷、风速、太阳辐射、弃电、缺电和电池状态等。此外,代码示例展示了如何运用GA求解,并绘制了发电单元的功率输出和年变化。该系统原理基于GA的自然选择和遗传原理,通过染色体编码、初始种群生成、适应度函数、选择、交叉和变异操作来寻找最优容量配置,以平衡成本、效率和可靠性。
|
8天前
|
机器学习/深度学习 算法
基于鲸鱼优化的knn分类特征选择算法matlab仿真
**基于WOA的KNN特征选择算法摘要** 该研究提出了一种融合鲸鱼优化算法(WOA)与K近邻(KNN)分类器的特征选择方法,旨在提升KNN的分类精度。在MATLAB2022a中实现,WOA负责优化特征子集,通过模拟鲸鱼捕食行为的螺旋式和包围策略搜索最佳特征。KNN则用于评估特征子集的性能。算法流程包括WOA参数初始化、特征二进制编码、适应度函数定义(以分类准确率为基准)、WOA迭代搜索及最优解输出。该方法有效地结合了启发式搜索与机器学习,优化特征选择,提高分类性能。
|
1天前
|
算法 安全 数据库
基于结点电压法的配电网状态估计算法matlab仿真
**摘要** 该程序实现了基于结点电压法的配电网状态估计算法,旨在提升数据的准确性和可靠性。在MATLAB2022a中运行,显示了状态估计过程中的电压和相位估计值,以及误差随迭代变化的图表。算法通过迭代计算雅可比矩阵,结合基尔霍夫定律解决线性方程组,估算网络节点电压。状态估计过程中应用了高斯-牛顿或莱文贝格-马夸尔特法,处理量测数据并考虑约束条件,以提高估计精度。程序结果以图形形式展示电压幅值和角度估计的比较,以及估计误差的演变,体现了算法在处理配电网状态估计问题的有效性。
|
3天前
|
机器学习/深度学习 存储 算法
基于SFLA算法的神经网络优化matlab仿真
**摘要:** 使用MATLAB2022a,基于SFLA算法优化神经网络,降低训练误差。程序创建12个神经元的前馈网络,训练后计算性能。SFLA算法寻找最优权重和偏置,更新网络并展示训练与测试集的预测效果,以及误差对比。SFLA融合蛙跳与遗传算法,通过迭代和局部全局搜索改善网络性能。通过调整算法参数和与其他优化算法结合,可进一步提升模型预测精度。