Redis高级---面试总结之内存过期策略及其淘汰策略

news2024/9/23 3:27:09

目前已更新系列:

当前:Redis高级---面试总结之内存过期策略及其淘汰策略

并发编程之----线程池ThreadPoolExecutor,Excutors的使用及其工作原理

Redis高级----主从、哨兵、分片、脑裂原理-CSDN博客

计算机网络--面试知识总结一

计算机网络-----面试知识总结二

计算机网络--面试总结三(Http与Https)

计算机网络--面试总结四(HTTP、RPC、WebSocket、SSE)-CSDN博客

知识积累之ThreadLocal---InheritableThreadLocal总结

过期策略

Redis中所有key-value的存储方式

Redis本身是一个典型的key-value内存存储数据库,因此所有的key、value都保存在之前学习过的Dict结构中。不过在其database结构体中,有两个Dict:一个用来记录key-value;另一个用来记录key-TTL。

  • Redis怎么知道key是过期的
    • 利用两个Dict分别记录key-value和key-ttl对
  • 是不是TTL到期了就立刻删除了尼?
    • 惰性删除
    • 周期删除

两种对过期key的删除策略

惰性删除

  • 概念:不是在TTL过期后就立刻删除,而是在访问一个key的时候,检查key的存活时间,如果已经过才执行删除
  • 存在的问题,当key过期了之后,在后面很长一段时间内都没有对该key的操作,那么就不能进行惰性删除了,所以引入了一种周期删除的策略

周期性删除

  • 通过一个定时任务,周期性的抽样部分过期的key,然后执行删除,随着时间的推移会去遍历数据库中不同的key直到把所有的key遍历过,因此就可以保证一个key只要是过期了的,那么早晚都会被检测到,就不会出现一个key长时间没访问导致没删除的现象,
  • 执行周期有两种
  • Redis会设置一个定时任务sererCron()(在服务器初始化的时候被定义的),按照server.hz(默认是10)的频率来执行过期key的清理,模式为SLOW,低频,每次清理的多
    • 刚开始默认初始化的时候会执行清理操作一次,以后每(1000/hz=100)100毫秒进行一次清理操作
  • Redis的每个时间循环前会调用beforeSleep()函数,执行过期key清理,模式为FAST,高频清理的少

周期性删除的两种模式
SLOW模式规则:低频,清理高时长
  • 执行频率受server.hz影响,默认为10,即每秒执行10次,每个执行周期100ms。
  • 执行清理耗时不超过一次执行周期的25%.默认slow模式耗时不超过25ms
  • 逐个遍历db,逐个遍历db中的bucket(哈希表数组的每一个下标,每一个下标上都一个一个链表),抽取20个key判断是否过期,然后将遍历到哪个buket放入到一个全局变量中,下一次就从该位置之后进行遍历处理
  • 如果没达到时间上限(25ms)并且过期key比例大于10%,再进行一次抽样,否则结束
    • 注意点:slow模式是最多25毫秒,因为当过期的key的比例小于全部key的10%那么就会提前结束
  • 执行完后再清理时间到100ms的时间内就都不会再调用该模式
FAST模式规则(过期key比例小于10%不执行 ):高频,清理低时长
  • 执行频率受beforeSleep()调用频率影响,但两次FAST模式间隔不低于2ms,不足2ms则直接跳过
  • 执行清理耗时不超过1ms
  • 逐个遍历db,逐个遍历db中的bucket,抽取20个key判断是否过期
    如果没达到时间上限(1ms)并且过期key比例大于10%,再进行一次抽样,否则结束

总结

Redis Key的TTL方式

  • 在Redis中是通过一个Dict记录每个key的TTL时间

过期key的删除策略

  • 惰性删除
  • 定期删除

为什么要使用惰性删除+周期性删除来实现过期策略尼
  • 资源利用:惰性删除和周期性删除的结合使用,使得Redis能够更加合理地利用CPU和内存资源。在不需要立即释放内存时,可以避免不必要的删除操作;在需要释放内存时,则可以通过周期性删除来清理过期的键。
  • 性能影响:与立即删除相比,惰性删除和周期性删除对Redis的性能影响更小。立即删除虽然可以立即释放内存,但会占用大量的CPU资源,影响缓存的响应时间和吞吐量。而惰性删除和周期性删除则可以在不影响缓存性能的前提下,逐步释放内存。

淘汰策略

8种淘汰策略

内存淘汰:当Redis内存使用达到设置的阈值,Redis主动挑部分key删除以释放更多内存的流程

Redis会在处理客服端命令的方法processCommand()中尝试做内存淘汰

Redis会在处理客服端命令的方法processCommand()中尝试做内存淘汰

Redis的8中淘汰策略来选择删除的key

可以通过配置文件来设置

  • noeviction:不淘汰任何key,但是内存满时不允许写于新的数据,默认就是这种策略
  • volatile-ttl:对设置了TTL的key,比较key的剩余TT值,TTL越小越先被淘汰
  • allkeys-random:对全体key,随即进行淘汰,也就是直接从db->dict中随机挑选
  • volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。
  • allkeys-lru: 对全体key,基于LRU算法进行淘汰
  • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu: 对全体key,基于LFU算法进行淘汰
  • volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰

记忆技巧:

以allkeys开头的表示就是对全体key进行操作,就是直接从db->dict总进行操作

以volatile开头的就是对储存过期时间的dict中去找,也就是从db->expires中

LRU(Least Recently Used):最少最近使用。用当前时间减去最后一次访问时间,则个值越大则淘汰优先级越高

LFU(Least Frequently Used):最少频率使用。统计每个Key的访问频率,值越小淘汰优先级越高

LRU、LFU在Redis种的处理及其具体算法

那么Redis怎么去记录每一个key上一次访问的时间,和怎么去记录每一个key的访问频率

通过上面lru关键字可看出来,使用LFU是高16位是以分钟位单位记录最近一次访问时间,低8位记录逻辑访问次数

这样设计的原因是,如果全部是用来作为统计次数,那么假设这种场景,刚开始时某一个key访问次数很高,然后之后的时间都不会进行访问,那么就会造成这种现象,该Key的统计次数很高,不会作为淘汰对象,这样就使得该使用不到的key一直放在内存中,所以这里采用了时间+统计次数的方式来计算

时间是用来使统计次数衰减的,后8位是用来进行逻辑计数的,因为8位最多范围为(0~255)很显然不够,所以设置了一下算法:

LFU的访问次数之所以叫做逻辑访问次数,是因为并不是每次key被访问都计数,而是通过概率计算算出来的逻辑访问次数,算法如下:

  • 生成0~1之间的随机数R
  • 计算P=1/ (旧次数 * lfu_log_factor + 1),记录为P,lfu_log_factor默认为10
  • 如果 R < P ,则计数器 + 1,且最大不超过255
  • 访问次数会随时间衰减,距离上一次访问时间每隔 lfu_decay_time 分钟,计数器 -1

其中衰减周期lfu_decay_time和计算因子lfu_log_factor都是可以通过配置文件设置的

通过该算法可以看到刚开始时就次数较小那么P=1/ (旧次数 * lfu_log_factor + 1)时p就较大,那么R < P 的概率就较大,此时计数器+1操作概率就较大

淘汰策略整体流程

注意:一开始随机挑选的5隔样本点,不管的的dileTime是否足够的(越大就说明越应该被淘汰),因为后面再次遍历,然后重复操作选取样本点的时候,进行内存判断策略后得到的dileTilme,放入池子中的条件为,池子未满,且池中最小的dileTime小于你要添加到池中的diletime这样替换下来,那么池子中总会保持diletime很大,即应该被淘汰。

总结:

Redis是可以设置内存上线的,Redis中为了防止内存达到上限有两种不同策略

  • 内存过期:内存过期后有两种删除策略,但是内存过期删除机制,只能删除过期了的数据,如果key都没过期且Redis中内存到达了上限,那么就交给内存淘汰机制来解决
    • 惰性删除:即当你访问时先检查一下有没有过期,过期了就删除
    • 周期删除:定期的任务,每隔一段时间就去删除一些过期的key
  • 内存淘汰
    • 有8中内存淘汰机制
    • 一个是no..:即只要内存不足就直接报错,默认
    • 两个随机的
    • 两个LFU
    • 连个LRU
    • 一个TTL

整体总结:

Redis中通过过期策略+内存淘汰策略来进行Redis的内存回收策略

其实可以理解为通过过期策略来主动清理内存,通过内存淘汰策略来进行兜底措施,即当通过策略清理后内存还是不够,那么就使用淘汰策略来进行强制性的操作

至于为什么过期策略是使用惰性删除+周期性删除来进行而不是直接key过期了就直接删除,我的理解就是是为了平衡cpu的使用,采用惰性删除+周期性这总,key过期了,我们不着急去删除,因为直接删除会使得CPU在删除上消耗过大,会影响此时redis的访问性能,而采用后面这种方式,相当于是将找一个合适的时机进行内存的清理,并且,清理的频率这些还是可以自己配置的,同时在redis4.0后还支持一步删除所以采用惰性删除+周期性删除来完成

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

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

相关文章

【深度学习】yolov8的微调

yolov8的集成度太高了&#xff0c;除了config的哪些参数以外&#xff0c;需要更精细的微调。 比如这里&#xff1a; https://github.com/ultralytics/ultralytics/blob/main/ultralytics/utils/tuner.py 应用场景&#xff0c;交通标志的向左转&#xff0c;向右转之类的&#x…

Golang | Leetcode Golang题解之第384题打乱数组

题目&#xff1a; 题解&#xff1a; type Solution struct {nums, original []int }func Constructor(nums []int) Solution {return Solution{nums, append([]int(nil), nums...)} }func (s *Solution) Reset() []int {copy(s.nums, s.original)return s.nums }func (s *Solu…

STM32G474之HAL_Delay()会导致死机的原因

使用HAL库需要HAL_Delay()函数支持&#xff0c;离开这个函数&#xff0c;和这个函数有关的函数就无法调用了。遇到这个问题&#xff0c;我们肯定会否定HAL库&#xff0c;也确实它是有点差&#xff0c;但也有好的一面。 为什么HAL库初始化了SysTick定时器&#xff0c;也使能了相…

书生大模型实战营(1)——InterStudio基础知识+Vscode SSH连接远程服务器+Linux基础指令

参加书生.浦江大模型实战训练营&#xff0c;学习大模型知识和微调技术&#xff0c;所有课程免费&#xff0c;通过闯关的形式学习&#xff0c;也比较有趣。一起来了解LLM的世界。邀请链接 产品简介 InternStudio 是大模型时代下的云端算力平台。基于 InternLM 组织下的诸多算法…

Android Handler消息机制完全解析(二)

欢迎转载&#xff0c;转载请注明出处&#xff1a;https://blog.csdn.net/dmk877/article/details/141690289 在阅读本篇博客之前建议先阅读此篇 Android Handler消息机制完全解析(一) 在看Looper源码之前必须要理解ThreadLocal&#xff0c;ThreadLocal在Handler消息机制中起到…

信息安全--(五)物理与环境安全技术(二)机房安全分析与防护

在使用本博客提供的学习笔记及相关内容时&#xff0c;请注意以下免责声明&#xff1a;信息准确性&#xff1a;本博客的内容是基于作者的个人理解和经验&#xff0c;尽力确保信息的准确性和时效性&#xff0c;但不保证所有信息都完全正确或最新。非专业建议&#xff1a;博客中的…

FlowUs 小程序:开启高效之旅,订阅内容超精彩

一、丰富多样的订阅选择 FlowUs 小程序提供了极为丰富的订阅内容。无论你是对知识管理、项目管理感兴趣&#xff0c;还是专注于创意写作、时间规划&#xff0c;都能在这里找到适合自己的订阅选项。从专业的行业资讯到实用的技巧指南&#xff0c;从激发灵感的创意案例到深入的学…

业务解耦-Spring事件监听的三种实现方式

实现ApplicationListener 步骤如下&#xff1a; 1.写Event类&#xff0c;需要继承Spring的ApplicationEvent类 2.写监听类&#xff0c;需要实现Spring的ApplicationListener接口&#xff0c;加上Component注解 3.监听类实现onApplicationEvent方法 4.通过ApplicationContext.p…

开放大世界的全局寻路

开放大世界的寻路一直是很困扰我的一个点&#xff0c;地图大、还是动态可变的&#xff0c;所以寻路会有很多要求。就我们项目来讲&#xff0c;有这几个要求&#xff1a; 能满足极大范围的地图&#xff1b; 地图寻路数据能实时构建&#xff0c;且重建代价很小&#xff1b; 寻路的…

地质灾害监测预警系统的作用

在地球的广阔舞台上&#xff0c;自然灾害如同不可预测的演员&#xff0c;时常上演着惊心动魄的剧目。地震的震撼、滑坡的肆虐、泥石流的咆哮&#xff0c;这些地质灾害不仅给人类生命财产带来巨大威胁&#xff0c;也考验着社会的防灾减灾能力。为了应对这一挑战&#xff0c;地质…

【Linux】在 bash shell 环境下,当一命令正在执行时,按下 control-Z 会?

目录 题目分析答案 题目 分析 ctrl-c&#xff1a; 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序&#xff1b;ctrl-z&#xff1a; 发送 SIGTSTP信号给前台进程组中的所有进程&#xff0c;常用于挂起一个进程&#xff1b;ctrl-d&#xff1a; 不是发送信…

乐城堡 JoyCastle Unity岗位笔试题

1)实现 move(GameObjct gameObject, Vector3 begin, Vector3 end, float time, bool pingpong){ } 使 gameObject 在 time 秒内&#xff0c;从 begin 移动到 end&#xff0c;若 pingpong 为 true&#xff0c;则在结束时 使 gameObject 在 time 秒内从 end 移动到 begin&#xf…

机器学习中的增量学习(Incremental Learning,IL)策略是什么?

机器学习中的增量学习&#xff08;Incremental Learning&#xff0c;IL&#xff09;策略是什么&#xff1f; 在当今快速发展的数据驱动世界中&#xff0c;传统的静态机器学习模型逐渐显露出局限性。随着数据量的增长和分布的变化&#xff0c;模型需要不断更新&#xff0c;以保…

opc da 服务器数据 转IEC61850项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 应用条件 2 4 查看OPC DA服务器的相关参数 2 5 配置网关采集opc da数据 4 6 用IEC61850协议转发数据 6 7 网关使用多个逻辑设备和逻辑节点的方法 9 8 在服务器上运行仰科OPC DA采集软件 10 9 案例总结 12 1 案例说明 在OPC DA服务…

使用 Vue3 Element Plus 实现el-table中的特定单元格编辑,下拉选择等

效果预览 完整代码(后面有解析) <template><div style="display: flex;align-items: center;justify-co

磁性齿轮箱市场报告:前三大厂商占有大约79.0%的市场份额

磁性齿轮箱是一种用于扭矩和速度转换的非接触式机构。它们无磨损、无摩擦、无疲劳。它们不需要润滑剂&#xff0c;并且可以针对其他机械特性&#xff08;如刚度或阻尼&#xff09;进行定制。 一、全球磁性齿轮箱行业现状与洞察 据 QYResearch 调研团队最新发布的“全球磁性齿轮…

成都高温限电:当电动汽车「无电可充」

8月末的成都&#xff0c;因为高温限电了。 近几日&#xff0c;成都市气象台连续发布了高温红色预警信号。据新华社报道&#xff0c;8月21日&#xff0c;四川电网用电负荷两次创下历史新高&#xff0c;最高达6797万千瓦&#xff0c;较去年最大用电负荷增长近13%&#xff0c;电力…

Golang | Leetcode Golang题解之第385题迷你语法分析器

题目&#xff1a; 题解&#xff1a; func deserialize(s string) *NestedInteger {index : 0var dfs func() *NestedIntegerdfs func() *NestedInteger {ni : &NestedInteger{}if s[index] [ {indexfor s[index] ! ] {ni.Add(*dfs())if s[index] , {index}}indexreturn…

HarmonyOS鸿蒙开发:在线短视频流畅切换最佳实践

简介 为了帮助开发者解决在应用中在线短视频快速切换时容易出现快速切换播放时延过长的问题&#xff0c;将提供对应场景的解决方案。 该解决方案使用&#xff1a; 视频播放框架AVPlayer和滑块视图容器Swiper进行短视频滑动轮播切换。绘制组件XComponent的Surface类型动态渲染…

挂载5T大容量外接硬盘到ubuntu

挂载5T大容量外接硬盘到ubuntu S1&#xff1a;查看硬盘 使用 $ sudo fdisk -l找到对应盘&#xff0c;例如下图所示 /dev/sdc S2: 创建分区 使用 $ sudo fdisk /dev/sdc对上硬盘进行创建分区&#xff1b;可以依次使用以下指令 m &#xff1a;查看命令&#xff1b; g &…