redis 从0到1完整学习 (十六):内存回收之 key 过期处理策略

文章目录

  • 1. 引言
  • 2. redis 源码下载
  • 3. redisDb 结构体
  • 4. Redis 过期 key 的处理策略
    • 4.1 惰性删除 (Lazy Expiration)
    • 4.2 定期删除 (Active Expire / Periodic Expiration)*
  • 5. 参考


1. 引言

前情提要:
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》
《redis 从0到1完整学习 (十二):RedisObject 之 List 类型》
《redis 从0到1完整学习 (十三):RedisObject 之 Set 类型》
《redis 从0到1完整学习 (十四):RedisObject 之 ZSet 类型》
《redis 从0到1完整学习 (十五):RedisObject 之 Hash 类型》

之前我们介绍了很多 redis 的 value 类型,包含 String、Set、Hash、List 等等,本文主要介绍 redis 的 key 过期处理策略,包含惰性清理、定期清理。

2. redis 源码下载

Redis 源码可以点击这里下载,方便查看其中定义的一些数据结构。
在这里插入图片描述

3. redisDb 结构体

Redis 数据库在 Redis 内部实现上是通过 redisDb 结构体来表示的。redisDb 结构体包含了特定数据库实例的所有信息,包括其键值对、过期时间、以及其它与该数据库相关的属性和功能。

源码结构体如下:
在这里插入图片描述

redisDb 结构体详细介绍:

typedef struct redisDb {dict *dict; // 一个字典,存储数据库中的所有键值对,键为 SDS 字符串,值为 redisObject 指针dict *expires; // 一个字典,存储了具有过期时间的键及其对应的 UNIX 时间戳dict *blocking_keys; // (如果支持事务阻塞的话)记录了正处于阻塞状态的键dict *watched_keys; // (如果支持 WATCH 命令的话)记录了被客户端监视的键int id; // 数据库编号,默认情况下 Redis 有 16 个数据库,编号从 0 到 15long long avg_ttl; // 平均剩余生存时间(TTL),用于统计分析和优化定期删除策略/* 其他相关字段 */
} redisDb;

具体字段可能会随着 Redis 不同版本而有所增减或调整。每个 redisDb 结构体代表 Redis 中的一个逻辑数据库,并且这些数据库都存放在全局的 redisServer 结构体的 db 数组中。用户可以通过 SELECT 命令切换到不同的数据库进行操作。

4. Redis 过期 key 的处理策略

Redis 源码中对于过期 key 的处理主要包括两种策略:惰性删除(Lazy Expiration)和定期删除(Active Expire)。

4.1 惰性删除 (Lazy Expiration)

当客户端尝试访问一个已过期的 key 时,Redis 会在返回给客户端 key 值之前检查该 key 是否已过期。如果发现 key 已过期,则会立即从数据库中删除该 key,并返回相应的响应(如 nil 表示不存在 key)。这种方式资源消耗少,但会导致过期 key 在被访问前一直占用内存空间。

robj *lookupKeyWriteWithFlags(redisDb *db, robj *key, int flags) {// 检查key是否过期,过期如果是惰性删除策略,则删除expireIfNeeded(db,key);return lookupKey(db,key,flags);
}int expireIfNeeded(redisDb *db, robj *key) {// 没有过期,返回if (!keyIsExpired(db,key)) return 0;...// 过期了,删除int retval = server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :...                                  	
}

4.2 定期删除 (Active Expire / Periodic Expiration)*

Redis 通过后台线程周期性地从数据库中随机抽取一定数量的 key 进行检查,以主动清理过期 key。这个过程由 redis.c 文件中的 expireIfNeeded() 函数在每次访问 key 时触发,以及由 db.c 文件中的 activeExpireCycle() 函数按照配置的周期来执行。Redis 使用一个名为“过期字典”(expired dict)的数据结构存储了所有设置了过期时间的 key 和它们对应的过期时间戳。

具体实现如下:

  1. Redis 定义了一个名为 activeExpireCycle 的函数,该函数会周期性地被调用,通常是由 Redis 主进程中的定时任务或者事件驱动触发。

  2. activeExpireCycle 函数会选择一定数量的数据库进行遍历,并对每个数据库中的一部分 key 进行随机抽样检查其过期时间。

  3. 检查过程中,Redis 会根据当前时间和 key 的过期时间戳判断 key 是否已过期。如果发现某个 key 已经过期,则立即将其从数据库中删除。

  4. Redis 会动态调整这个清理过程的速度和范围,以尽量保证不过于频繁地消耗 CPU 资源,同时又能及时清理掉大量过期的 key,避免内存资源浪费。执行周期有两种模式:

    • SLOW 模式规则:
      • 执行频率受 server.hz 影响,默认为10,即每秒执行10次,每个执行周期100ms。
      • 执行清理耗时不超过一次执行周期的25%。默认 slow 模式耗时不超过25ms
      • 逐个遍历 db,逐个遍历 db 中的 bucket,抽取20个 key 判断是否过期
      • 如果没达到时间上限(25ms)并且过期 key 比例大于10%,再进行一次抽样,否则结束
    • FAST 模式规则(过期 key 比例小于10%不执行 ):
      • 执行频率受 beforeSleep() 调用频率影响,但两次FAST模式间隔不低于2ms
      • 执行清理耗时不超过1ms
      • 逐个遍历 db,逐个遍历 db中的 bucket,抽取20个 key 判断是否过期
        如果没达到时间上限(1ms)并且过期 key 比例大于10%,再进行一次抽样,否则结束
  5. 在实际操作中,Redis 也会根据服务器的负载情况、已使用内存与 maxmemory 设置等因素灵活调整清理策略,确保系统性能和资源的有效利用。

总的来看,定期删除是一种主动但又较为温和的过期 key 清理策略,它配合惰性删除共同维护了 Redis 内存的高效管理。
这两种机制结合使用可以确保 Redis 在不过度消耗 CPU 资源的情况下,有效地管理过期 key,从而避免内存浪费。同时,Redis 也会尽可能保证过期数据不会长时间不被清理。

5. 参考

《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》
《redis 从0到1完整学习 (十二):RedisObject 之 List 类型》
《redis 从0到1完整学习 (十三):RedisObject 之 Set 类型》
《redis 从0到1完整学习 (十四):RedisObject 之 ZSet 类型》
《redis 从0到1完整学习 (十五):RedisObject 之 Hash 类型》

欢迎关注本人,我是喜欢搞事的程序猿; 一起进步,一起学习;

也欢迎关注我的wx公众号:一个比特定乾坤

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

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

相关文章

Lumerical Monitors------frequency domain power monitor 频率域功率监视器

frequency domain power monitor 频率域功率监视器 引言正文引言 这里给大家介绍一下 frequency domain power monitor。 正文 首先,我们可以通过以下方式添加 frequency domain power monitor 到我们的工程文件中: 在 general tab 中,有一个共同的监视器设置 simulati…

苍穹外卖Day01——总结1

总结1 1. 软件开发整体介绍1.1 软件开发流程1.2 角色分工1.3 软件环境 2. 苍穹外卖项目介绍2.1 项目介绍2.2 技术选项 3. Swagger4. 补充内容(待解决...) 1. 软件开发整体介绍 1.1 软件开发流程 1.2 角色分工 从角色分工里面就可以查看自己以后从事哪一…

跨国制造业组网方案解析,如何实现总部-分支稳定互联?

既要控制成本,又要稳定高效,可能吗? 在制造企业积极向“智造”发展、数字化转型的当下,物联网、人工智能、机器人等新型设备加入到生产、管理环节,为企业内部数据传输提出了更高的要求。而当企业规模扩大,数…

记录一次接近24万条数据导入Mysql的过程

由于开发项目的需求,之前有部分数据要写入阿里云的表格存储,过了一年多时间,表A的数据量接近24万条,现在需要将表A的数据转到Mysql中。 利用官方工具导出数据后,发现文件里面有238999条数据,文件大小是460…

Unity中URP下深度图的线性转化

文章目录 前言一、_ZBufferParams参数有两组值二、LinearEyeDepth1、使用2、Unity源码推导:3、使用矩阵推导: 三、Linear01Depth1、使用2、Unity源码推导3、数学推导: 前言 在之前的文章中,我们实现了对深度图的使用。因为&#…

C语言中常用的字符串函数(strlen、sizeof、sscanf、sprintf、strcpy)

C语言中常用的字符串函数 文章目录 C语言中常用的字符串函数1 strlen函数2 sizeof函数2.1 sizeof介绍2.2 sizeof用法 3 sscanf函数3.1 sscanf介绍3.2 sscanf用法3.3 sscanf高级用法 4 sprintf函数4.1 背景4.2 sprintf用法 5 strcpy函数5.1 strcpy介绍5.1 strcpy用法 1 strlen函…

【Internal Server Error】pycharm解决关闭flask端口依然占用问题

Internal Server Error The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. 起因: 我们在运行flask后,断开服务依然保持运行&#xff0…

web端播放rtsp视频流(摄像头监控视频)教程

文章目录 前言一、ffmpeg是什么?二、ffmpeg安装1.下载2.安装 三、node搭建websocket服务四、web客户端播放视频 前言 像海康大华一些摄像头或者直播源 为rtsp视频流,想在web上播放必须进行协议转换。已知一些方案例如rtsp转rtmp需要flash,现…

网站被挂黑链怎么办

网站被挂黑链这种事情总是防不胜防,且不说网站本身的安全防护做的是否到位,但只要被盯上了就难逃厄运。即使是企业机构的网站也难逃被黑的经历,更何况用户苦心经营的网站,因此首先需要正确看待挂黑链这个现象,网站被挂…

如何实现在IDEA中远程访问家里或者公司的数据库远程协作开发

文章目录 1. 本地连接测试2. Windows安装Cpolar3. 配置Mysql公网地址4. IDEA远程连接Mysql小结 5. 固定连接公网地址6. 固定地址连接测试 IDEA作为Java开发最主力的工具,在开发过程中需要经常用到数据库,如Mysql数据库,但是在IDEA中只能连接本…

十一、HTML 图像

1、插入图像 本例演示如何在网页中显示图像。 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>插入图像</title> </head><body><p>一个图像:<img src"smiley.gif" alt"Smiley …

使用Android Compose实现网格列表滑到底部的提示信息展示

文章目录 概述1 效果对比1.1 使用添加Item的办法&#xff1a;1.2 使用自定义的方法 2. 效果实现2.1 列表为空时的提示页面实现2.2 添加Item的方式代码实现2.3 使用自定义的方式实现 3. UI工具类 概述 目前大多数的APP都会使用列表的方式来呈现内容&#xff0c;例如淘宝&#x…

C#,入门教程(12)——数组及数组使用的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(11)——枚举&#xff08;Enum&#xff09;的基础知识和高级应用https://blog.csdn.net/beijinghorn/article/details/123917587 数组是一种数据集合&#xff0c;是一组完全相同的、按顺序存放的数据。 需要记住数组的几个特征&…

如何查询关键词的KD与搜索量

随着海外贸易的不断发展&#xff0c;越来越多的小伙伴们从事外贸行业&#xff0c;但是随着面对有限的市场和激烈的竞争&#xff0c;很多从业者往往流量的来源比较单一&#xff0c;那就是付费流量&#xff0c;包括谷歌ads&#xff0c;facebook等一些投流广告。广告的好处是当你付…

OpenMMLab教程:OpenMMLab介绍与安装

一、 OpenMMLab介绍 OpenMMLab 是一个用于学术研究和工业应用的开源算法体系&#xff0c;于2018年年中开始&#xff0c;由 MMLab&#xff08;香港中文大学多媒体实验室&#xff09;和商汤科技联合启动。OpenMMLab 致力于为计算机视觉领域的重要方向创建统一且开源的代码库&…

开始卷TED:第1篇 —— 《Embrace the near win》—— part: 2

But this is the thing: What gets us to convert success into mastery? 问题来了&#xff1a;我们如何将一次成功转化为卓越的成就呢&#xff1f; mastery convert This is a question I’ve long asked myself. I think it comes when we start to value the gift of a n…

图连通性,Tarjan算法

前言 通常说的Tarjan算法指的是计算机科学家Robert Tarjan提出的多个与图连通性有关的算法&#xff0c;通常包括&#xff1a; 强连通性 有向图的强连通分量&#xff08;SCC&#xff09;缩点 无向图的边双连通性 割边无向图的边双连通&#xff08;e-DCC&#xff09;分量缩点 无…

美餐支付 - PHP代碼实现

前言 背景 前段时间&#xff0c;因接手的项目需要实现 美餐支付 的功能对接 在此记录一下鄙人的实现步骤&#xff0c;方便有需要的道友参考借鉴 场景描述 我们的 “现代膳食” 售卖机&#xff0c;可以在屏幕上显示可配送的餐食 用户选中商品后&#xff0c;点击购买 选择 “美餐…

铸铁检验平台主要应用在哪些行业中——河北北重

铸铁检验平台可应用于以下行业&#xff1a; 汽车制造业&#xff1a;用于检验汽车零部件的铸铁材质和质量&#xff0c;以确保零部件的可靠性和耐用性。 机械制造业&#xff1a;用于检验铸铁机械零部件的质量和性能&#xff0c;以确保机械设备的稳定运行。 建筑工程&#xff1a…

《罗素论教育》笔记

目录 全书架构 书简介 经典摘录 一、教育的理想 教育的基本原理 教育的目的 二、品性的教育 一岁前的教育 主要是2岁到6岁的教育 三、智力教育 14岁前的课程安排 最后的学年 大学教育 四、结束语 全书架构 书简介 经典摘录 一、教育的理想 教育的基本原理 1、我…