结合源码分析Redis的内存回收和内存淘汰机制,LRU和LFU是如何进行计算的?

article/2025/8/4 10:00:57

Redis 内存回收

1. 过期 key 处理

Redis 之所以性能强,最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大,会影响持久化或主从同步性能。我们可以通过修改配置文件来设置Redis的最大内存:

当内存使用达到上限时,就无法存储更多数据了。为了解决这个问题,Redis 提供了一些策略实现内存回收,在学习 Redis 缓存的时候我们说过,可以通过 expire 命令给 Redis 的 key 设置 TTL(存活时间),key 的 TTL 到期以后,再次访问 name 返回的是 nil,说明这个 key 已经不存在了,对应的内存也得到释放。从而起到内存回收的目的

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

Redis 的 DB 结构

Redis是如何知道一个key是否过期呢?

利用两个 Dict 分别记录 key-value 对及 key-ttl

是不是 TTL 到期就立即删除了呢?

  1. 惰性删除:顾明思议并不是在 TTL 到期后就立刻删除,而是在访问一个 key 的时候,检查该 key 的存活时间,如果已经过期才执行删除
  1. 周期删除:顾明思议是通过一个定时任务,周期性的抽样部分过期的 key,然后执行删除,执行周期有两种
    • 初始化时设置定时任务serverCron(),按照 server.hz 的频率来执行过期 key 清理,模式为 SLOW
    • Redis 每个事件循环前都会调用beforeSlepp()函数,执行过期 Key 清理,模式为 Fast

SLOW 模式规则:

  • 执行频率受 server.hz 影响,默认为 10,即每秒执行 10 次,每个执行周期 100ms
  • 执行清理耗时不超过一次执行周期的 25%,默认 slow 模式耗时不超过 25ms
  • 逐个遍历 db,逐个遍历 db 中的 bucket(hash 表的角标),抽取 20 个 key 判断是否过期
  • 如果没达到时间上限(25ms)并且过期 key 比例大于 10%,再进行一次抽样,否则结束

FAST 模式规则(过期 key 比例小于 10% 不执行 ):

  • 执行频率受beforeSleep()调用频率影响,但两次 FAST 模式间隔不低于 2ms
  • 执行清理耗时不超过 1ms
  • 只会采样存在明显过期积压的 DB/Bucket,抽取 20 个 key 判断是否过期如果没达到时间上限(1ms)并且过期 key 比例大于 10%,再进行一次抽样,否则结束

Redis 的 SLOW 和 FAST 两种定期过期删除本质上都是由主线程串行执行的,不会并发执行。即使是不同扫描模式,也只是调度频率不同,删除操作永远是串行的,因此不会出现多个线程同时对同一个 bucket 释放内存,也就自然防止了冲突和数据错误

模式

触发时机

调度点

典型频率

目标

SLOW

serverCron100ms/次

主线程定时

10Hz

全局定期均匀采样

FAST

beforeSleep/压力感知

主线程调度插入

ms 级别

过期压力下快速补刀

RedisKey 的 TTL 记录方式:

  • 在 RedisDB 中通过一个 Dict 记录每个 Key 的 TTL 时间

过期 key 的删除策略:

  • 惰性清理:每次查找 key 时判断是否过期,如果过期则删除
  • 定期清理:定期抽样部分 key,判断是否过期,如果过期则删除

定期清理的两种模式:

  • SLOW 模式执行频率默认为 10,每次不超过 25ms
  • FAST 模式执行频率不固定,但两次间隔不低于 2ms,每次耗时不超过 1ms

2. 内存淘汰策略

内存淘汰:就是当 Redis 内存使用达到设置的上限时,主动挑选部分 key 删除以释放更多内存的流程,Redis 会在处理客户端命令的方法 processCommand() 中尝试做内存淘汰:

淘汰策略

Redis支持 8 种不同策略来选择要删除的 key

  1. noeviction: 不淘汰任何 key,但是内存满时不允许写入新数据,默认就是这种策略
  2. volatile-ttl: 对设置了 TTL 的 key,比较 key 的剩余 TTL 值,TTL 越小越先被淘汰
  3. allkeys-random:对全体 key ,随机进行淘汰,也就是直接从db->dict中随机挑选
  4. volatile-random:对设置了 TTL 的 key ,随机进行淘汰,也就是从db->expires中随机挑选
  5. allkeys-lru: 对全体 key,基于LRU算法进行淘汰
  6. volatile-lru: 对设置了 TTL 的 key,基于LRU算法进行淘汰
  7. allkeys-lfu: 对全体 key,基于LFU算法进行淘汰
  8. volatile-lfu: 对设置了 TTL 的 key,基于LFU算法进行淘汰比较容易混淆的有两个:
    • LRU(Least Recently Used),最少最近使用(最近使用的时间越小越容易被淘汰)。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
    • LFU(Least Frequently Used),最少频率使用。会统计每个 key 的访问频率,值越小淘汰优先级越高

Redis的数据都会被封装为 RedisObject 结构:

LFU的访问次数之所以叫做逻辑访问次数,是因为并不是每次 key 被访问都计数,而是通过运算:

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

LFU的逻辑访问次数中,如果一个 key 访问的频率越高,那么他的逻辑访问次数递增的概率将会越低,最多递增到 255;其次LFU的逻辑访问次数,会在距离上一次访问间隔lfu_decay_time分组,进行递减

内存淘汰策略:从源码角度分析内存的淘汰策略流程,首先插入 key 时,发现内存已满,Redis 首先判断是否设置了noeviction策略;如果没有设置,那么将判断淘汰策略中是否从Allkeys中进行淘汰,当策略为Allkeys时将从dict中进行选取,反之从expires中选取。然后进一步判断采用内存策略是Random还是LRU/LFU/TTL?如果是RANDOM那么遍历 DB 之后进行随机淘汰;如果是LRU/LFU/TTL,首先 key 的淘汰将会在eviction_pool中完成。在选取 DB 之后,还是会先随机选取maxmemory-sample个 key,然后才会根据不同的策略去进行判断。eviction-pool中是根据一个值进行升序排序之后,将最大的值进行淘汰。LRU/LFU/TTL这三种淘汰策略,我们不可能给每一种都设置一个排序机制,所以 Redis 巧妙的采用了idleTime进行统一标准的判断。对于TTL而言,idleTime等于maxTTL-TTL减去 TTL 剩余有效期,maxTTL-TTL就是 long 的最大值,如果 key 的有效期越短那么idleTime的值也会越大,也就符合idleTime升序排序并淘汰最大的 key;对于LRU而言,idleTime等于当前时间戳减去 key 的时间戳,key 的最少最近访问时间戳越小,代表 key 很久没有被查询,idleTime的值也会越大;最后LFUidleTime计算是 255-LFU 的计数,如果计数越小,说明这个值就越大

Redis 的内存淘汰机制基于一定的概率进行选择,虽然在一开始的时候,可能会出现不合理的清除,但是随着时间的增加,这个淘汰机制的正确率还是很乐观的


http://www.hkcw.cn/article/rFyDxPXHTr.shtml

相关文章

NLP学习路线图(十五):TF-IDF(词频-逆文档频率)

在自然语言处理&#xff08;NLP&#xff09;的浩瀚宇宙中&#xff0c;TF-IDF&#xff08;词频-逆文档频率&#xff09; 犹如一颗恒星&#xff0c;虽古老却依然璀璨。当ChatGPT、BERT等大模型光芒四射时&#xff0c;TF-IDF作为传统方法的代表&#xff0c;其简洁性、高效性与可解…

C++11(上)

历史&#xff1a; 在C98版本后&#xff0c;C11是一次大版本的更新。在C11中新增了许多有用的东西。接下来将由小编来带领大家介绍C11中新增的内容。 列表初始化: 在C中&#xff0c;列表初始化&#xff08;也称为统一初始化或花括号初始化&#xff09;是一种使用花括号 {} 来初…

从TCO角度分析IBM Cognos Analytics

一、总拥有成本&#xff08;TCO&#xff09;分析 像 Cognos Analytics 这样成熟的企业级 BI 平台&#xff0c;在与新兴的敏捷 BI 工具竞争中&#xff0c;依然能够保持其独特价值和竞争力的关键所在&#xff0c;尤其从企业和组织的长远发展、团队协作以及总拥有成本&#xff08…

使用西门子博图V16时遇到了搜索功能报错的问题,提示缺少SIMATIC Visualization Architect组件怎么办,全网首发

先上解决方案&#xff0c;这个太简单了&#xff0c;直接上官网下载&#xff0c;这个安装包40M&#xff0c;很快就下载完了&#xff0c;然后直接安装就可以了。 官网链接SIMATIC Visualization Architect V16 TRIAL Download - ID: 109772966 - Industry Support Siemens 今天我…

STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联

目录 一、STM32G4 电机外设篇&#xff08;三&#xff09; TIM1 发波 和 ADC COMP DAC级联1 TIM1 高级定时器发波1.1 stm32cubemx配置 2 TIM1 ADC COMP DAC级联2.1 stm32cubemx配置 附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^) 一、STM32G4 电机外设篇&#xff08;三&…

12 Java GUI

Java 在图形开发中的占比并不是特别突出&#xff0c;尤其在传统的客户端图形界面开发方面。不是现代 UI 设计的首选 C#的WinForms&#xff08;传统&#xff09;、WPF&#xff08;现代&#xff09;是Windows 桌面开发的王者 跨平台&#xff08;Windows/macOS/Linux&#xff09;&…

当AI遇见千年古韵:解密“古韵智绘”,让传统纹样焕发新生机

目录: 引言:当千年古韵遇上AI,一场跨越时空的对话“古韵智绘”:不止于复刻,更是创新的引擎核心技术揭秘:AI如何“理解”并“创作”传统纹样? 基石:海量纹样数据库与智能特征提取神笔:基于GANs的AI纹样生成器魔术:风格迁移与融合的艺术桥梁:交互式编辑与开放API接口系…

[AD] Reaper NBNS+LLMNR+Logon 4624+Logon ID

QA QAForela-Wkstn001 的 IP 位址是什麼&#xff1f;172.17.79.129Forela-Wkstn002 的 IP 位址是什麼&#xff1f;172.17.79.136被攻擊者竊取雜湊值的帳戶的使用者名稱是什麼&#xff1f;arthur.kyle攻擊者用來攔截憑證的未知設備的 IP 位址是什麼&#xff1f;172.17.79.135受…

RAG入门之数据导入

LangChain 是什么 LangChain 是一个用于构建基于大语言模型&#xff08;LLM&#xff09;应用的开源框架。它提供了一套工具和抽象&#xff0c;让开发者能够轻松构建复杂的AI应用。 LangChain 的核心功能 文档加载和处理&#xff1a;支持多种格式&#xff08;PDF、文本、网页…

科研学习|科研软件——激活后的Origin导出图时突然出现了demo水印

问题&#xff1a;画完图在导出图形时&#xff0c;导出的图有demo水印&#xff0c;如下图。 解决方法1&#xff1a;右击选择以管理员身份运行。 解决方法2&#xff1a;找到该软件的保存路径&#xff0c;双击Origin64.exe

一:UML类图

类之间的关系 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 学习设计模式的第一步是看懂UML类图&#xff0c;类图能直观的表达类、对象之间的关系&#xff0c;这将有助于后续对代码的编写。 常见的类之间的关系包括&#xff1a;继承…

Python数学可视化——环境搭建与基础绘图

Python数学可视化——环境搭建与基础绘图 数学函数可视化入门&#xff08;一次函数/三角函数&#xff09; 本节将建立Python科学计算环境&#xff0c;并创建基础函数绘图工具&#xff0c;可生成一次函数和三角函数的可视化图像&#xff0c;同时结合物理中的匀速直线运动案例。…

mask2former训练自己的语义分割数据集

一、环境配置 1.1下载源码 mask2former: https://github.com/facebookresearch/Mask2Former/tree/maindetectron2: https://github.com/facebookresearch/detectron2下载完后&#xff0c;新建一个文件夹&#xff0c;起个名字&#xff08;我起的Mask2Former-main&#xff09…

如何使用1panel部署linux网站

找到官网&#xff0c;尝试一下在线安装 如果在线不成功&#xff0c;试一下离线安装 按照指令一步步执行即可&#xff0c;注意换成新版本的名称即可 如果成功&#xff0c;你会看到这个页面 1Panel Log]: [1Panel Log]: 感谢您的耐心等待&#xff0c;安装已完成 [1Panel Log]:…

个人用户进行LLMs本地部署前如何自查和筛选

一、个人用户硬件自查清单&#xff08;从核心到次要&#xff09; 1. 显卡&#xff08;GPU&#xff09;——决定性因素 显存容量&#xff08;关键指标&#xff09;&#xff1a; 入门级&#xff08;8~12GB&#xff09;&#xff1a;可运行7B模型&#xff08;4bit量化&#xff09;…

java Map双列集合

单列集合&#xff1a;一次只能添加一个元素 双列集合&#xff1a;一次添加两个元素&#xff0c;左边的叫键&#xff08;唯一的不能重复&#xff09;&#xff0c;右边叫值&#xff08;可以重复&#xff09;&#xff0c;键和值一一对应。这样一对叫&#xff1a;键值对/键值对对象…

在IIS上无法使用PUT等请求

错误来源&#xff1a; chat:1 Access to XMLHttpRequest at http://101.126.139.3:11000/api/receiver/message from origin http://101.126.139.3 has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource. 其实我的后…

FastVLM: Efficient Vision Encoding for Vision Language Models——为视觉语言模型提供高效的视觉编码

这篇文章的核心内容是介绍了一种名为 FastVLM 的新型视觉语言模型&#xff08;VLM&#xff09;&#xff0c;它通过一种高效的视觉编码器 FastViTHD&#xff0c;在高分辨率图像输入下实现了显著的性能提升和延迟降低。以下是文章的主要研究内容总结&#xff1a; 1. 研究背景与动…

关于开发板连接电脑找不到CH340解决方法大全(附ch340驱动下载链接)

一、一般开发板只需要一根支持传输数据的usb线就可以&#xff0c;找不到就是驱动没安装&#xff0c;一般win11系统会自动后台安装&#xff0c;如果没安装需要手动 ch340驱动官网&#xff1a;南京沁恒微电子股份有限公司 安装还失败就用这个&#xff08;安装之后重启电脑就可以了…

Flask文件处理全攻略:安全上传下载与异常处理实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…