与expire和pexpire类似,客户端也可以通过exporeat或者pexpireat命令,以秒或者毫秒精度来给数据库中的某个键设置过期时间(expire time)。
过期时间是一个UNIX时间戳,当键的过期时间来临时,服务器就会自动从数据库中删除这个键。
TTL命令与PTTL命令可以返回一个带有生存时间或者过期时间的键的剩余生存时间。
Redis有四个不同的命令可以用来设置键的生存时间,不过这四种命令最后都会转化为pexpireat命令。
首先expire命令可以转换成pexpire(秒转毫秒)
接着,pexpire命令可以转换成pexpireat命令(将剩余时间加上当前的UNIX时间作为键的过期UNIX时间)
并且expireat命令也可以转换成pexpireat命令(秒转毫秒)
如何保存过期时间
下图是一个数据库某个DB的实例:
dict的dict用来保存数据库键(key-value对)
expires的dict用来保存设置有过期时间的对象。
如何移除过期时间
persist命令可以移除一个键的过期时间:
persist就是pexpireat命令的反操作:persist命令在过期字典(expires-dict)中查找给定的键,并接触键和值在过期字典中的关联。
过期键的判定:
1.检查给定键是否存在过期字典,如果存在,则取得键的过期时间
2.检查当前的UNIX时间戳是否大于键的过期时间,大于的话则键已经过期:
Redis中过期键的删除策略:
定时删除对内存友好,对CPU不友好(过期的键会被尽快删除,同一时间过期键太多会消耗很多cpu资源)
惰性删除对cpu友好,对内存不友好(程序只会在取出键时才会对键进行过期检查,不会在检查其他无关键上花费cpu时间)
定期删除是对上面两种方式的一种整合和折中:
定期删除策略每隔一段时间执行依次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,除此之外,通过定期删除过期键,定期删除策略有效减少了因为过期键而带来的内存浪费。
定期删除策咯的难点时确定删除操作执行的时长和频率。
定期删除策略的实现:
RDB对过期键的处理:
保存快照时,过期键不会被保存到RDB中。
载入RDB文件时
作为主服务器模式运行载入RDB文件时,会对文件中的键进行检查,将过期键剔除(所以过期键的载入不会影响)
作为从服务器运行载入RDB时,会将所有的数据载入数据库,不过由于主从服务器同步,从服务器的数据库会被情况,所以一般来讲,过期键的载入对从服务器也不会造成影响。
AOF文件写入:
当服务器以AOF持久化模式运行时,如果数据库中某个键已经过期,但是它还没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生任何影响。
当过期键被惰性或者定期删除后,程序会向AOF文件追加一条DEL命令来表示该键已经被删除。
AOF文件重写
在执行AOF文件重写时,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的AOF文件中,所以数据库中包含过期键不会对AOF重写造成影响。
复制:
当服务器运行在主从复制模式下时,从服务器的过期键删除动作有主服务器控制:
主从复制如果客户端向从服务器获取一个已经过期的键,从服务器将返回这个键(从服务器没有权力del)。
只有放主服务器收到get时,检查键过期时才会将自身和所有从服务器的这个过期键删除。