Redis过期键删除策略

如果一个键过期了,那么它什么时候会被删除呢?

这个问题有三种可能的答案,它们分别代表了三种不同的删除策略:

1.定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。

2.惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。

3.定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

在这三种策略中,第一种和第三种为主动删除策略,而第二种则为被动删除策略。

定时删除

定时删除策略对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存。

另一方面,定时删除策略的缺点是,它对CPU时间是最不友好的:在过期键比较多的情况下,删除过期键这一行为河能会占用相当一部分CPU时间,在内存不紧张但是CPU时间非常紧张的情况下,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。

例如,如果正有大量的命令请求在等待服务器处理,并且服务器当前不缺少内存,那么服务器应该优先将CPU时间用在处理客户端的命令请求上面,而不是用在删除过期键上面。

除此之外,创建一个定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式——无序链表,查找一个事件的时间复杂度为0(N)——并不能高效地处理大量时间事件。

因此,要让服务器创建大量的定时器,从而实现定时删除策略,在现阶段来说并不现实。

惰性删除

惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行,并且删除的目标仅限于当前处理的键,这个策略不会在删除其他无关的过期键上花费任何CPU时间。

惰性删除策略的缺点是,它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。

在使用惰性删除策略时,如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问到的话,那么它们也许永远也不会被删除(除非用户手动执行FLUSHDB),我们甚至可以将这种情况看作是一种内存泄漏——无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放它们,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息。

举个例子,对于一些和时间有关的数据,比如日志(log),在某个时间点之后,对它们的访问就会大大减少,甚至不再访问,如果这类过期数据大量地积压在数据库中,用户以为服务器已经自动将它们删除了,但实际上这些键仍然存在,而且键所占用的内存也没有释放,那么造成的后果肯定是非常严重的。

定期删除

从上面对定时删除和惰性删除的讨论来看,这两种删除方式在单一使用时都有明显的缺陷:

定时删除占用太多CPU时间,影响服务器的响应时间和吞吐量。

惰性删除浪费太多内存,有内存泄漏的危险。

定期删除策略是前两种策略的一种整合和折中:

定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。

除此之外,通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费。

定期删除策略的难点是确定删除操作执行的时长和频率:

如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上面。

如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。

因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。

前面我们讨论了定时删除、惰性删除和定期删除三种过期键删除策略,Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。

接下来我们将对Redis服务器中惰性删除和定期删除的具体实现进行说明。

惰性删除策略的实现

过期键的惰性删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查:

如果输入键已经过期,那么expireIfNeeded函数将输入键从数据库中删除。

如果输入键未过期,那么expireIfNeeded函数不做动作。

命令调用expireIfNeeded函数的过程如下图所示。

expireIfNeeded函数就像一个过滤器,它可以在命令真正执行之前,过滤掉过期的输入键,从而避免命令接触到过期键。

另外,因为每个被访问的键都可能因为过期而被expireIfNeeded函数删除,所以每个命令的实现函数都必须能同时处理键存在以及键不存在这两种情况:

当键存在时,命令按照键存在的情况执行。

当键不存在或者键因为过期而被expireIfNeeded函数删除时,命令按照键不存在的情况执行。

举个例子,下图展示了GET命令的执行过程,在这个执行过程中,命令需要判断键是否存在以及键是否过期,然后根据判断来执行合适的动作。

 

定期删除策略的实现

过期键的定期删除策略由redis.c/activeExpireCycle函数实现,每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。

整个过程可以用伪代码描述如下:

#默认每次检查的数据库数量
DEFAULT DB NUMBERS = 16#默认每个数据库检查的键数量
DEFAULT KEY NUMBERS = 20#全局变量,记录检查进度
current_db = 0
def activeExpireCycle();#初始化要检查的数据库数量#如果服务器的数据库数量比 DEFAULT_DB_NUMBERS 要小#那么以服务器的数据库数量为准if server.dbnum < DEFAULT_DB_NUMBERS;db_numbers = server.dbnumelse:db_numbers = DEFAULT_DB_NUMBERS#遍历各个数据库for i in range (db_numbers);#如果current_db的值等于服务器的数据库数量#这表示检查程序已经遍历了服务器的所有数据库一次#将current_db重置为0,开始新的一轮遍历if current_db == server.dbnum;current_db = 0#获取当前要处理的数据库redisDb = server.db[current_db]#将数据库索引增1,指向下一个要处理的数据库current_db += 1#检查数据库键for j in range (DEFAULT_KEY_NUMBERS);#如果数据库中没有一个键带有过期时间,那么跳过这个数据库if redisDb.expires.size() == 0: break .#随机获取一个带有过期时间的键key_with_ttl = redisDb.expires.get_random_key()#检查键是否过期,如果过期就删除它if is_expired(key_with_ttl);delete_key(key_with_ttl)#已达到时间上限,停止处理if reach_time_limit(): return

activeExpireCycle函数的工作模式可以总结如下:

函数每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。

全局变量current_ db会记录当前activeExpireCycle函数检查的进度,并在下一次activeExpireCycle函数调用时,接着上一次的进度进行处理。比如说,如果当前activeExpireCycle函数在遍历10号数据库时返回了,那么下次activeExpireCycle函数执行时,将从11号数据库开始查找并删除过期键。

随着activeExpireCycle函数的不断执行,服务器中的所有数据库都会被检查一遍,这时函数将current_ db变量重置为0,然后再次开始新一轮的检查工作。

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

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

相关文章

Spring 创建和使用

文章目录 创建 Spring 项目1. 创建一个Maven项目2. 添加 Spring 框架支持3. 添加启动类 存储 Bean 对象创建一个 Bean将 Bean 注册到容器 获取并使用 Bean 对象创建 Spring 上下文获取指定的 Bean 对象使用 Bean 对象 getBean() 的用法总结 创建 Spring 项目 1. 创建一个Maven…

数据结构----结构--线性结构--链式存储--链表

数据结构----结构–线性结构–链式存储–链表 1.链表的特点 空间可以不连续&#xff0c;长度不固定&#xff0c;相对于数组灵活自由 搜索&#xff1a; 时间复杂度O(n) 增删: 头增头删时间复杂度O(1) 其他时间复杂度为O(n) 扩展&#xff1a;单向循环链表的特性 从任意节…

zookeeper+kafka分布式消息队列集群的部署

目录 一、zookeeper 1.Zookeeper 定义 2.Zookeeper 工作机制 3.Zookeeper 特点 4.Zookeeper 数据结构 5.Zookeeper 应用场景 &#xff08;1&#xff09;统一命名服务 &#xff08;2&#xff09;统一配置管理 &#xff08;3&#xff09;统一集群管理 &#xff08;4&…

C语言有关文件的操作

打开文件与关闭文件 在编写代码时&#xff0c;我有一个习惯是“保证一一对应”。 写下代码fopen()之后&#xff0c;还没有写对文件进行增删查改等操作的代码&#xff0c;先立刻写上fclose()&#xff0c;避免忘记关闭FILE* fd的情况。 不关闭fd&#xff0c;在fopen()次数较少的…

SAP度量单位转换功能

针对今天N2项目提出业务痛点&#xff1a;物料30011110的基本单位是KG&#xff0c;在XXX的BOM里单位是G&#xff0c;由于物料没配单位转换关系&#xff0c;但系统又能正常进行转换&#xff0c;开发需要技术支持。 经专项调查&#xff0c;G和KG的转换是SAP相同量纲转换标准功能&…

限流式保护器在高校宿舍电气防火的应用

安科瑞 华楠 引言 14日早晨6时10分左右&#xff0c;上海商学院徐汇校区学生宿舍楼发生火灾&#xff0c;4名女生从六楼宿合阳台跳下逃生当场死亡&#xff0c;酿成近年来惨烈的校园事故。宿舍火灾初步判断缘起于寝室里使用热得快导致电器故障并将周围可燃物引燃。 任何条生命都是…

Kafka与Zookeeper版本对应关系

文章目录 了解版本对应Kafka安装包Kafka源码包 了解 比如&#xff1a; kafka_2.11-1.1.1.jar包 其中2.11表示的是Scala的版本&#xff0c;因为Kafka服务器端代码完全由Scala语音编写。”-“后面的1.1.1表示的kafka的版本信息。遵循一个基本原则&#xff0c;Kafka客户端版本和服…

DC-8靶机

DC-8官网地址 信息收集 靶机MAC&#xff1a; 00:0C:29:3A:46:A1 主机发现 nmap -sP 192.168.80.0/24端口扫描 nmap -A -p- 192.168.80.142访问80端口 点击页面能点击的地方&#xff0c;发现每点击一个链接&#xff0c;地址栏的?nid后面的数字就会变 尝试在数字后面加个 引…

virtuoso 打开时没有原装的库

如果virtuoso打开没有下列库&#xff0c;一般是virtuoso的启动路径下的cds.lib文件配置错误 打开启动路径下的cds.lib文件&#xff0c;输入 SOFTINCLUDE “cadence安装路径”/IC617/share/cdssetup/cds.lib

快速解决IDEA中类的图标变成J,不是C的情况

有时候导入新的项目后&#xff0c;会出现如下情况&#xff0c;类的图标变成J&#xff0c;如图&#xff1a; 直接上解决方法: 找到项目的pom.xml&#xff0c;右键&#xff0c;在靠近最下方的位置找到Add as Maven Project&#xff0c;点击即可。 此时&#xff0c;一般类的图标就…

nginx实战

文章目录 nginx实战安装环境 实战主要学习静态网站配置基于端口的多虚拟主机访问日志 nginx代理服务 nginx实战 linux下如何安装一个工具 yum工具安装&#xff0c;自动下载nginx&#xff0c;且安装到固定的位置 源代码编译安装&#xff0c;更适合于专业的&#xff0c;企业服务…

任务12、Quality指令加持,Midjourney生成电影级数码作品

12.1 任务概述 本次实验任务旨在帮助你掌握Midjourney AI绘画中的Quality指令。通过深入介绍Quality指令的概念和作用,我们将解释为什么它在绘画中至关重要。通过测试不同的Quality参数对绘画效果的影响,并提供实战演示,你将学会如何在Midjourney中设置Quality参数以达到更…

MFC创建和使用OCX控件

文章目录 MFC建立OCX控件注册OCX控件与反注册使用Internet Explorer测试ocx控件OCX控件添加方法OCX控件添加事件Web使用OCX控件MFC使用OCX控件使用OCX控件调用ocx的功能函数对ocx的事件响应OCX控件调试工具tstcon32.exe加载ocx控件使用tstcon32.exe调试ocxMFC建立OCX控件 新建…

Q-Vision+Kvaser CAN/CAN FD/LIN总线解决方案

智能联网技术在国内的发展势头迅猛&#xff0c;随着汽车智能化、网联化发展大潮的到来&#xff0c;智能网联汽车逐步成为汽车发展的主要趋势。越来越多整车厂诉求&#xff0c;希望可以提供本土的测量软件&#xff0c;特别是关于ADAS测试。而Softing中国推出的Q-Vision软件不仅可…

PyCharm新手入门指南

安装好Pycharm后&#xff0c;就可以开始编写第一个函数&#xff1a;Hello World啦~我们就先来学习一些基本的操作&#xff0c;主要包含新建Python文件&#xff0c;运行代码&#xff0c;查看结果等等。 文章主要包含五个部分&#xff1a; 一、界面介绍 主要分为菜单栏、项目目录…

本地开发 npm 好用的http server、好用的web server、静态服务器

好用的web server总结 有时需要快速启动一个web 服务器&#xff08;http服务器&#xff09;来伺服静态网页&#xff0c;安装nginx又太繁琐&#xff0c;那么可以考虑使用npm serve、http-server、webpack-dev-server。 npm serve npm 的serve可以提供给http server功能&#…

前端进阶js02----null和undefined的区别

1.相同点 1)都是原始类型的值且保存在栈中。 2) 在布尔运算中都会被认为是false 2.不同点 1&#xff09;null是js的关键字&#xff0c;表示空值&#xff1b;undefined不是关键字&#xff0c;是一个全局变量。 2&#xff09;值相同&#xff0c;但类型不一样 值相同&#xff1a…

Deep Image Prior:《Deep Image Prior》经典文献阅读总结与实现

文章目录 Deep Image Prior1. 方法原理1.1 研究动机1.2 方法 2. 实验验证2.1 去噪2.2 超分辨率2.3 图像修复2.4 消融实验 3. 总结 Deep Image Prior 1. 方法原理 1.1 研究动机 动机 深度神经网络在图像复原和生成领域有非常好的表现一般归功于神经网络学习到了图像的先验信息…

《合成孔径雷达成像算法与实现》Figure3.5

clc clear all close all%参数设置 TBP 100; %时间带宽积 T 10e-6; %脉冲持续时间%参数计算 B TBP/T; %信号带宽 K B/T; …

SolidUI社区-提示词链式思考(CoT)

背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目&#xff0c;旨在将自然语言处理&#xff08;NLP&#xff09;与计算机图形学相…