当前位置: 首页 > news >正文

Redis内存回收:过期策略与淘汰策略

Redis 数据库结构

Redis 作为典型的键值内存存储数据库,所有的键值对(key - value)都存储在之前学习过的 Dict 结构里。在其database结构体(redisDb)中,包含多个重要的 Dict 以及其他属性:

  • dict *dict:用于存放所有的 key 及对应的 value,这部分也被称为 keyspace
  • dict *expires:专门存放每一个设置了 TTL(存活时间)的 key 及其对应的 TTL 存活时间
  • dict *blocking_keys:记录有客户端在等待数据(比如通过 BLPOP 命令)的 key。
  • dict *ready_keys:存储接收到 PUSH 操作的被阻塞的 key。
  • dict *watched_keys:为 MULTI/EXEC(事务)以及 CAS(比较并交换)操作所监控的 key。
  • int id:数据库的 ID,范围是 0 到 15。
  • long long avg_ttl:用于记录平均 TTL 时长。
  • unsigned long expires_cursor:在进行 expire 检查时,在 dict 中抽样的索引位置。
  • list *defrag_later:等待进行碎片整理的 key 列表。

过期策略

惰性删除

并非在 TTL(存活时间)到期后就立即删除 key,而是在访问一个 key 的时候,检查该 key 的存活时间,如果已经过期才执行删除操作

具体执行

在查找一个 key 执行写操作(lookupKeyWriteWithFlags 函数)和读操作(lookupKeyReadWithFlags 函数)时,都会调用 expireIfNeeded 函数来检查 key 是否过期expireIfNeeded 函数的逻辑是:先判断 key 是否过期,如果未过期直接结束并返回 0;如果过期,则删除过期的 key 并进行相关传播操作,然后返回 1。

周期删除

通过一个定时任务,周期性地抽样部分过期的 key,然后执行删除操作。执行周期有两种。

执行周期

  • Redis 服务初始化函数 initServer() 中设置定时任务:按照 server.hz 的频率来执行过期 key 清理,模式为 SLOW。
  • Redis 的每个事件循环前调用 beforeSleep() 函数:执行过期 key 清理,模式为 FAST。

具体执行

  • 在 initServer 函数中,会创建定时器,关联回调函数 serverCron,处理周期取决于 server.hz(默认 10)。
  • serverCron 函数会更新 lruclock 到当前时间,为后期的 LRU(最近最少使用)和 LFU(最不经常使用)淘汰策略做准备,还会执行数据库的数据清理,比如过期 key 处理(调用 databasesCron 函数)。
  • databasesCron 函数会尝试清理部分过期 key,清理模式默认为 SLOW(调用 activeExpireCycle 函数并传入 ACTIVE_EXPIRE_CYCLE_SLOW)。
  • 在 beforeSleep 函数中,尝试清理部分过期 key,清理模式默认为 FAST(调用 activeExpireCycle 函数并传入 ACTIVE_EXPIRE_CYCLE_FAST)。

SLOW 模式

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

FAST 模式

  • 执行频率受 beforeSleep() 调用频率影响,但两次 FAST 模式间隔不低于 2ms
  • 执行清理耗时不超过 1ms。
  • 逐个遍历 db,逐个遍历 db 中的 bucket,抽取 20 个 key 判断是否过期。
  • 如果没达到时间上限(1ms)并且过期 key 比例大于 10%,再进行一次抽样,否则结束。

淘汰策略

当Redis内存使用达到设置的阈值时,Redis主动挑选部分Key删除

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

支持8种策略来选择要删除的key:

  • noeviction:不淘汰任何 key,但是内存满时不允许写入新数据,默认就是这种策略。
  • volatile-ttl:对设置了 TTL 的 key,比较 key 的剩余 TTL 值,TTL 越小越先被淘汰
  • allkeys-random:对全体 key,随机进行淘汰。也就是直接从 db->dict 中随机挑选
  • volatile-random:对设置了 TTL 的 key,随机进行淘汰。也就是从 db->expires 中随机挑选。
  • allkeys-lru:对全体 key,基于 LRU 算法进行淘汰(最少未使用,它认为在最近一段时间内使用频率低或者没有被使用的 key 是最有可能不再被使用的。)
  • volatile-lru:对设置了 TTL 的 key,基于 LRU 算法进行淘汰
  • allkeys-lfu:对全体 key,基于 LFU 算法进行淘汰(最不经常使用,将访问次数最少的 key 视为最不经常被使用的,从而优先淘汰。)
  • volatile-lfu:对设置了 TTL 的 key,基于 LFI 算法进行淘汰

淘汰流程

Redis 内存淘汰流程如下:

  1. 首先判断内存是否充足,若充足则流程结束。
  2. 若内存不充足,判断内存策略是否为NO_EVICTION,若是则流程结束。
  3. 若不是NO_EVICTION,判断是否为AllKeys模式:
    • 若是,从db->entriesdb->dict中淘汰。
    • 若不是,进入后续内存策略判断。
  4. 判断内存策略:
    • 若为LRULFUTTL策略:
      • 准备一个eviction_pool
      • 获取下一个 DB,随机挑选maxmemory_samples数量的 key。
      • 根据内存策略,分别用maxTTL - TTLTTL策略)、nowTime - LRU值LRU策略)、255 - LFU计数LFU策略)作为idleTime
      • 判断是否可以存入eviction_pool,若可以则按idleTime升序存入。
      • 若有下一个 DB,重复上述步骤;若没有,倒序从eviction_pool中获取一个 key 删除。
    • 若为RANDOM策略:遍历 DB,随机挑选一个 key 删除。
  5. 删除 key 后,判断已释放内存是否满足需要释放的内存,若满足则流程结束;若不满足,重复上述淘汰步骤。


文章转载自:

http://fXTWG6eF.ycgrL.cn
http://hwmjO9wr.ycgrL.cn
http://9VYiGWYi.ycgrL.cn
http://6lkU0tMf.ycgrL.cn
http://8hhK1i7L.ycgrL.cn
http://L4NhvFfQ.ycgrL.cn
http://PUMDGV6X.ycgrL.cn
http://gZNTHYx2.ycgrL.cn
http://t0wvZCD0.ycgrL.cn
http://c87YvBE0.ycgrL.cn
http://BhCzXokd.ycgrL.cn
http://rDgmg9mr.ycgrL.cn
http://CvVlqtky.ycgrL.cn
http://krIQbKnB.ycgrL.cn
http://0VQsGIn7.ycgrL.cn
http://jIfTEQi2.ycgrL.cn
http://C4hUfn9b.ycgrL.cn
http://TC1R9HDk.ycgrL.cn
http://UV9Dqrf6.ycgrL.cn
http://PABnRF34.ycgrL.cn
http://4dZjmB9m.ycgrL.cn
http://bFhbQnCO.ycgrL.cn
http://Dc89ZX3O.ycgrL.cn
http://ziq7pjgR.ycgrL.cn
http://AM3aLHiD.ycgrL.cn
http://Cg3lr7Qd.ycgrL.cn
http://67WtDles.ycgrL.cn
http://1kgRV0bD.ycgrL.cn
http://2o4jTica.ycgrL.cn
http://6yXqyIZG.ycgrL.cn
http://www.dtcms.com/a/382559.html

相关文章:

  • 【css学习笔记9】品优购项目
  • 动态规划解决网格路径问题
  • 金融科技:企业和机构银行
  • C++ 异常
  • One-hot encoding|独热编码
  • AI论文速读 | VisionTS++:基于持续预训练视觉主干网络的跨模态时间序列基础模型
  • 如何学习VBA_3.3.9:利用“搭积木”思想,快速有效地完成你的代码
  • 《使用深度学习统一时间相位展开框架》论文总结
  • Windows下使用PerfMon进行性能监控并记录日志
  • 微信小程序开发教程(十二)
  • 【攻防实战】记一次攻防实战全流程
  • 【编号520】全国4500多个地震灾害点位数据(2021.2-2025.8)
  • 牛客网习题题解(持续更新中...)
  • 2025.8.20--python基础温习
  • PCIE地址空间介绍
  • (三)BLE协议栈协议分层架构设计详解--图文结合通俗易懂
  • 主板硬件研发基础--DP/DP++
  • 287. 寻找重复数
  • 《从像素到认知:用 Keras 构建图像分类 CNN 的实战指南》
  • 深入探索 Python 元组:从基础到高级应用
  • Java 黑马程序员学习笔记(进阶篇5)
  • DENOISING DIFFUSION IMPLICIT MODELS
  • Gradle 安装与配置 环境配置 仓库管理 项目介绍 优缺点介绍
  • Replit CEO演讲:软件开发的未来与AI代理革命
  • LeetCode 3541.找到频率最高的元音和辅音:计数(位运算)
  • 使用Python创建本地Http服务实现与外部系统数据对接
  • Redis 线上问题排查简版手册
  • python学习之基本库/第三方库的认识和学习
  • 深度解析电动汽车绝缘材料的性能测试标准与解决方案
  • 通讯工程师专业实务-数据库、软件开发、云计算