Redis中设置主键失效的命令有:EXPIRE、EXPIREAT、PEXPIRE、PEXPIREAT、SETEX和PSETEX。一旦key设置的过期时间到期
就会删除该key-value。那么Redis是如何让key失效的呢?
当我们往redis中存入key-value时,key会添加到一个key的字典表dict中;同时如果该key有过期时间,那么过期时间添加到expires字典表中;
这两个字典表可以理解为分别是key:value和key:timeout的映射。当我们使用SETEX和PSETEX时,先将key添加到dict中,然后将过期时间添加到expires中;而使用EXPIRE、EXPIREAT、PEXPIRE、PEXPIREAT时,先检查dict中是否存在该主键,如果有就将主键和过期时间添加到expires中。
被动失效方法是在任何访问数据操作前,如,GET、MGET、HGET、LRANGE等等,先检查主键是否失效,如果失效就删除它。具体做法如下:
主键失效广播做两件事,1.如果redis开启了AOF就将删除失效主键的这一操作以 DEL Key 的标准命令格式记录下来;2. 如果redis存在slave, 就给所有的slave发送
DEL Key的标准命令格式消息,告诉slave删除各自的失效主键。
仅仅通过被动失效远远不够,如果一个主键一直不被再次访问那么它将永远不会被删除,显示造成很大的空间浪费。Redis还提供主动失效的方法,简单说就是每隔一段时间
(默认10秒)检查一下数据库,从中删除失效主键。在redis服务器启动时,创建一个时间事件用来检查失效主键,这个检查时间默认10秒执行一次,设置失效的主键并不是所有的全部检查而是随机选择一定数量(默认10个)进行检查并且删除,如果失效主键的超过抽检样本比例的25%,Redis会认为当前数据失效主键很多,所以还会进行下一轮的检查直到比例小于25%,然后转向下一个数据库。同样redis也不会一次检查所有的数据库,而是一次最多处理16个数据库。这样做的目的是为了减少清理失效主键带来的性能下降。
主动检查主键的具体做法是:
主动失效的算法可以在redis.conf中选择,随机,LRU和ttl。
上面我们可以看到,定期检查失效主键需要对数据库遍历和对expires字典遍历,虽然redis设置了检查的数量和cpu执行时间限制,但是当失效主键很多时还是会影响性能,特别是短期内的失效时间,因此在使用失效时间还是要注意的。