在学习Redis的过程中,了解其内存回收功能至关重要。我们知道Redis的内存是有上限的,当内存占满时若不加以处理,就无法继续写入新的数据。Redis主要通过两种机制来解决内存不足的问题,本篇我们先来深入探讨一下Redis对于过期Key的处理方式。
一、设置Key的过期时间
在之前学习Redis基本命令时,我们了解到Redis中有一个EXPIRE
命令,它可以给Key设置一个TTL(Time To Live),也就是Key的存活时间。例如,我们设置一个名为name
的Key,其值为杰克
,并设置过期时间为5秒钟。在刚存入这个Key后,我们可以立刻访问并获取到它的值,但5秒钟过后再去取时,就会发现拿不到值了,这表明该Key已经过期,其在内存中已被回收,从而释放出了更多的内存空间。
二、Redis如何判断Key是否过期
Redis是键值型数据库,其所有数据都保存在一个名为RedisDB
的结构体中,该结构体里包含两个重要的哈希表:
(一)dict哈希表
它主要用于保存Redis中写入的所有键值对数据,里面的每个entry
就是原始的键值对。
(二)expires哈希表
这个哈希表比较特殊,它用于保存那些添加了过期时间的Key及其到期时间。这里的到期时间是通过写入Key的时间加上设置的TTL值来确定的。
当我们向Redis里设置一个键值对时,如果同时给这个Key设置了过期时间,那么Redis不仅会将该键值对保存到dict
哈希表中,还会将Key及其到期时间保存到expires
哈希表中(注意,在expires
哈希表中只保存Key和到期时间,不保存Key对应的值,这样可以减少内存占用)。
这样一来,当我们想要知道一个Key是否过期时,只需到expires
哈希表中拿着Key去查询,就能查到它的到期时间,然后将其与当前时间进行比较,便可立即得知该Key是否过期。这就是Redis判断一个Key是否过期的基本原理。
三、过期Key的删除策略
当Redis知道一个Key过期后,并不会立即将其删除,而是采用了延时删除的策略,主要包括以下两种方式:
(一)惰性删除
所谓惰性删除,是指当有一个命令要操作一个Key时(比如查询该Key),此时才会去判断这个Key的过期时间是否已经到了。如果到期了,就会把它删除。但这也存在一个问题,就是如果一个Key已经到期,但一直没有人来查询它,那么它就不会被删除,可能会造成内存浪费。
(二)定期删除
为了解决惰性删除可能导致的内存浪费问题,Redis还采用了定期删除的方式。在Redis内部,会有定期执行的任务,它会周期性地去抽样一部分带有TTL的Key,具体做法是从expires
哈希表中随机挑选一些Key出来,然后查看这些Key是否过期,如果过期了就将其删除。这样,即便某些Key后续没有被访问,也有可能通过定期删除发现其过期并进行删除。
定期删除的定时任务有两种模式:
1. slow模式
这种模式的执行频率相对较慢,默认是每秒10次,该值可以在redis config
文件中通过server.hz
进行配置(hz
表示频率)。需要注意的是,虽然默认每秒10次看起来每次有100毫秒,但实际上它内部会做判断,如果执行时长超过25毫秒,就不再执行了。也就是说,在每次任务执行过程中,它可能会进行多次抽样删除操作,一旦执行时间达到25毫秒,就会停止本次抽样。
2. fast模式
这种模式的执行频率比slow模式要高很多,但其具体频率是不确定的,它是跟随Redis内部的IO事件循环去执行的。Redis采用IO多路复用的机制,内部有一个不断循环执行的任务(可理解为死循环),该任务会不断判断是否有新的网络IO请求(如写请求、读请求等)进来并进行处理。在处理正常IO事件之外,它还会进行周期的删除操作,即抽样一些Key进行删除。
不过,fast模式也有一些限制条件。虽然IO事件循环本身频率非常高,但要求每两次任务之间的间隔不能低于两毫秒,如果低于两毫秒,就会跳过本次IO循环,等到下一次再去判断。同时,每一次执行定期删除任务的时长不能超过一毫米,即在一次IO循环内进行抽样删除操作时,速度会很快,可能远低于一毫秒且可能多次删除,但一旦判断超过一毫秒,就会停止操作。
通过结合惰性删除和定期删除这两种模式,Redis能够更充分地抽样那些过期Key并将其清理掉,从而释放更多的内存。
四、总结回顾
本节课我们详细学习了Redis过期Key的处理机制,主要内容如下:
(一)TTL的记录方式
Redis中有一个RedisDB
的结构体,内部包含两张哈希表。一张记录原始的键值对数据,另一张记录设置了到期时间的Key及其到期时间(到期时间为存入时的时间加上TTL)。
(二)过期Key的删除策略
过期Key的删除有惰性删除和定期删除两种方式。惰性删除是在每次对Key进行操作时判断其是否过期并删除;定期删除则是通过定期执行的任务,周期性地抽样Key判断是否过期并进行删除。定期清理的模式又分为slow和fast两种:slow模式执行频率相对较低,默认每秒10次,每次执行时长不超过25毫秒;fast模式频率更高且跟随IO循环执行,虽频率高但有间隔和时长限制(两次间隔不低于两毫秒,每次执行时长不超过一毫秒)。
评论