Redi设置过期键及Redis的过期键的删除策略

Redis设置过期键

通过EXPIRE命令或者PEXPIRE命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间(Time To Live,TTL),在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间为0的键:
在这里插入图片描述

与EXPIRE命令和PEXPIRE命令类似,客户端可以通过EXPIREAT命令或PEXPIREAT命令,以秒或者毫秒精度给数据库中的某个键设置过期时间( expire time ),过期时间是一个UNIX时间戳,当键的过期时间来临时,服务器就会自动从数据库中删除这个键:

TTL命令和PTTL命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间,也就是,返回距离这个键被服务器自动删除还有多长时间:
在这里插入图片描述

Redis如何设置过期时间?

Redis有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除):

  • EXPIRE<key> <ttl>命令用于将键key的生存时间设置为ttl秒
  • PEXPIRE<key> <ttl>命令用于将键key的生存时间设置为ttl毫秒
    -EXPIREAT<key> <timestamp>命令用于将键key的过期时间设置为timestamp所指定的秒数时间戳。
  • PEXPIREAT<key> <timestamp>命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳。

虽然有多种不同单位和不同形式的设置命令,但实际上EXPIRE、PEXPIRE、EXPIREAT三个命令都是使用PEXPIREAT命令来实现的:无论客户端执行的是以上四个命令中的哪一个,经过转换之后,最终的执行效果都和执行PEXPIREAT命令一样。

Redis如何保存过期时间的?

redisDb结构的expires字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典:

  • 过期字典的键是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)。
  • 过期字典的值是一个long long类型的整数,这个整数保存了键所指向的数据库键的过期时间———―个毫秒精度的 UNIX时间戳。

在这里插入图片描述
下图展示了一个带有过期字典的数据库例子,在这个例子中,键空间保存了数据库中的所有键值对,而过期字典则保存了数据库键的过期时间。
在这里插入图片描述
图中的过期字典保存了两个键值对:

  • 第一个键值对的键为alphabet键对象,值为1385877600000,这表示数据库键alphabet的过期时间为1385877600000 ( 2013年12月1日零时)。
  • 第二个键值对的键为book键对象,值为1388556000000,这表示数据库键book的过期时间为13885560000o0 ( 2014年1月1日零时)。

其他

Redis如何移除过期时间?

PERSIST命令就是PEXPIREAT命令的反操作:PERSIST命令在过期字典中查找给定的键,并解除键和值(过期时间)在过期字典中的关联。
在这里插入图片描述

Redis如何计算并返回剩余生存时间?

在这里插入图片描述

Redis如何判断键是否过期?

通过过期字典,程序可以用以下步骤检查一个给定键是否过期:

  • 检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间。
  • 检查当前UNIX时间戳是否大于键的过期时间:如果是的话,那么键已经过期;否则的话,键未过期。

过期键删除策略

经过上面的介绍,我们知道了数据库键的过期时间都保存在过期字典中,又知道了如何根据过期时间去判断一个键是否过期,现在剩下的问题是:如果一个键过期了,那么它什么时候会被删除呢?

三种不同的删除策略:

  • 定时删除:在设置键的过期时间的同时,创建一个定时器( timer ),让定时器在键的过期时间来临时,立即执行对键的删除操作。
  • 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
    在这三种策略中,第一种和第三种为主动删除策略,而第二种则为被动删除策略。

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

定时删除

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

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

惰性删除

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

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

惰性删除的实现

见redis设计与实现 9.6.1

定期删除

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

  • 定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。
  • 除此之外,通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费。

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

  • 如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上面。
  • 如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况。

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

定期删除的实现

见redis设计与实现 9.6.2

AOF、RDB和复制功能对过期键的处理

AOF对过期键的处理

  1. AOF文件写入

    当服务器以AOF持久化模式运行时,如果数据库中的某个键已经过期,但它还没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生任何影响。

    当过期键被惰性删除或者定期删除之后,程序会向AOF文件追加(( append)一条DEL命令,来显式地记录该键已被删除。

    举个例子,如果客户端使用GET message命令,试图访问过期的message键,那么服务器将执行以下三个动作:

    • 从数据库中删除message键。
    • 追加一条DEL message命令到AOF文件。
    • 向执行GET命令的客户端返回空回复。
  2. AOF文件载入

    和生成RDB文件时类似,在执行AOF重写的过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的AOF文件中。

    举个例子,如果数据库中包含三个键k1、k2、k3,并且k2已经过期,那么在进行重写工作时,程序只会对k1和k3进行重写,而k2则会被忽略。

    因此,数据库中包含过期键不会对AOF重写造成影响。

RDB对过期键的处理

  1. 生成RDB文件

    在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中

    举个例子,如果数据库中包含三个键k1、k2、k3,并且k2已经过期,那么当执行SAVE命令或者BGSAVE命令时,程序只会将k1和 k3的数据保存到RDB文件中,而k2则会被忽略。

    因此,数据库中包含过期键不会对生成新的RDB文件造成影响。

  2. 载入RDB文件

    在启动Redis服务器时,如果服务器开启了RDB 功能,那么服务器将对RDB文件进行载入:

    • 如果服务器以主服务器模式运行,那么在载人RDB文件时,程序会对文件中保存的键进行检查,**未过期的键会被载入到数据库中,而过期键则会被忽略,**所以过期键对载入RDB文件的主服务器不会造成影响。

    • 如果服务器以从服务器模式运行,那么在载人RDB文件时,文件中保存的所有键,不论是否过期,都会被载入到数据库中。不过,因为主从服务器在进行数据同步的时候,从服务器的数据库就会被清空,所以一般来讲,过期键对载入RDB文件的从服务器也不会造成影响。

    举个例子,如果数据库中包含三个键k1、k2、k3,并且 k2已经过期,那么当服务器启动时:

    • 如果服务器以主服务器模式运行,那么程序只会将k1和 k3载人到数据库,k2会被忽略。
    • 如果服务器以从服务器模式运行,那么k1、k2和k3都会被载入到数据库。

复制功能对过期键的处理

当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制:

  • 主服务器在删除一个过期键之后,会显式地向所有从服务器发送一个DEL命令,告知从服务器删除这个过期键。
  • 从服务器在执行客户端发送的读命令时,即使碰到过期键也不会将过期键删除,而是继续像处理未过期的键一样来处理过期键。
  • 从服务器只有在接到主服务器发来的DEL命令之后,才会删除过期键。

参考:redis设计与实现

猜你喜欢

转载自blog.csdn.net/weixin_44533129/article/details/112681008
今日推荐