「每天一道面试题」Redis过期策略及实现原理
wptr33 2024-12-17 16:47 44 浏览
Redis过期策略及实现原理
描述
我们在使用 Redis 时,一般会设置一个过期时间,当然也有不设置过期时间的,也就是永久不过期。当我们设置了过期时间,Redis 是如何判断是否过期,以及根据什么策略来进行删除的。
redis过期时间设置
语法
# 以秒为单位设置过期,这是最常用的方式
EXPIRE KEY time
# 字符串独有的方式
SETEX KEY_NAME TIMEOUT VALUE说明
除了 字符串 自己独有设置过期时间的方法外,其他方法都需要依靠 EXPIRE 方法来设置时间,如果没有设置时间,那缓存就是永不过期。
如果设置了过期时间,之后又想让缓存永不过期,使用 persist KEY。
三种过期策略
定时删除
含义
在设置 KEY 的过期时间的同时,为该 KEY 创建一个定时器,让定时器在 KEY 的过期时间来临时,对 KEY 进行删除。
优点
该方法可以保证内存被尽快释放。
缺点
若过期 KEY 很多,删除这些 KEY 会占用很多的 CPU 时间,在 CPU 时间紧张的情况下,CPU 不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些 KEY。
定时器的创建耗时,若为每一个设置过期时间的 KEY 创建一个定时器(将会有大量的定时器产生),性能影响严重。
懒汉式删除
含义
KEY 过期的时候不删除,每次通过 KEY 获取值的时候去检查是否过期,若过期,则删除,返回 null。
优点
删除操作只发生在通过 KEY 取值的时候,而且只删除当前 KEY,所以对 CPU 时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的 KEY 了)。
缺点
若大量的 KEY 在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)。
定期删除
含义
每隔一段时间执行一次删除过期 KEY 操作。
优点
通过限制删除操作的时长和频率,来减少删除操作对 CPU 时间的占用。
缺点
在内存友好方面,不如 ”定时删除”(会造成一定的内存占用,但是没有懒汉式那么占用内存),在 CPU 时间友好方面,不如 ”懒汉式删除”(会定期的去进行比较和删除操作,cpu 方面不如懒汉式,但是比定时好)。
难点是合理设置删除操作的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)(这个要根据服务器运行情况来定了),每次执行时间太长,或者执行频率太高对 cpu 都是一种压力。每次进行定期删除操作执行之后,需要记录遍历循环到了哪个标志位,以便下一次定期时间来时,从上次位置开始进行循环遍历。
说明
memcached 只是用了惰性删除,而 redis 同时使用了惰性删除与定期删除,这也是二者的一个不同点(可以看做是 redis 优于 memcached 的一点)。
对于懒汉式删除而言,并不是只有获取 KEY 的时候才会检查 KEY 是否过期,在某些设置 KEY 的方法上也会检查,比如 SETNEX 命令,因为 SETNX 命令是在 KEY 不存在的情况下才设置,因为,如果不做过期 KEY 检查,那么直接设置,就会与我们原来的意思相违背。
定时任务
单线程的 redis,如何知道要运行定时任务?
redis 是单线程的,线程不但要处理定时任务,还要处理客户端请求,线程不能阻塞在定时任务或处理客户端请求上,那么,redis 是如何知道何时该运行定时任务的呢?
Redis 的定时任务会记录在一个称为最小堆的数据结构中。这个堆中,最快要执行的任务排在堆的最上方。在每个循环周期,Redis 都会将最小堆里面已经到点的任务立即进行处理。处理完毕后,将最快要执行的任务还需要的时间记录下来,这个时间就是接下来处理客户端请求的最大时长,若达到了该时长,则暂时不处理客户端请求而去运行定时任务。
配置
Redis 中定期删除使用的是统一的一个定时器,定时器执行的时长默认为 10,具体配置如下:
提高它的值将会占用更多的 cpu,当然相应的 redis 将会更快的处理同时到期的许多 key,以及更精确的去处理超时。 hz 的取值范围是 1~500,通常不建议超过 100,只有在请求延时非常低的情况下可以将值提升到 100。
Redis采用的过期策略
说明
Redis 采用的是懒汉式删除+定期删除。
懒汉式删除流程
- 在进行 GET 或 SETNX 等操作时,先检查 KEY 是否过期;
- 若过期,删除 KEY,然后执行相应操作;
- 若没过期,直接执行相应操作;
定期删除流程
简单而言,对指定 N 个库的每一个库随机删除小于等于指定 M 个过期 KEY,具体流程如下:
- 遍历每个数据库(就是 redis.conf 中配置的 ”database” 数量,默认为 16)
- 检查当前库中的指定个数个 KEY(默认是每个库检查 20 个 KEY,注意相当于该循环执行 20 次,循环体是下边的描述)
- 如果当前库中没有一个 KEY 设置了过期时间,直接执行下一个库的遍历随机
- 获取一个设置了过期时间的 KEY,检查该 KEY 是否过期,如果过期,删除 KEY 判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。
对于定期删除,在程序中有一个全局变量 current_db 来记录下一个将要遍历的库,假设有 16 个库,我们这一次定期删除遍历了 10 个,那此时的 current_db 就是 11,下一次定期删除就从第 11 个库开始遍历,假设 current_db 等于 15 了,那么之后遍历就再从 0 号库开始(此时 current_db==0)。
参考文章:嗨客网 Redis 过期策略及实现原理
相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)
