首页 > 编程知识 正文

redis设置过期时间的方法,redis可以不设置过期时间吗

时间:2023-05-03 10:59:49 阅读:285715 作者:3219

前言

用过Redis的应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除。但是有时候我们会发现有些设置过过期时间的key并没有在我们设置的时间点失效。这里我们来详细聊一下有关过期时间的问题。

设置过期时间需要注意的事项

1、 DEL/SET/GETSET等命令会清除过期时间

在使用DEL、SET、GETSET等会覆盖key对应value的命令操作一个设置了过期时间的key的时候,会导致对应的key的过期时间被清除。

//设置mykey的过期时间为500s127.0.0.1:6379> set tkey test ex 500OK//查看过期时间127.0.0.1:6379> ttl tkey (integer) 294//使用set命令覆盖tkey的内容127.0.0.1:6379> set tkey updatetestOK//过期时间被清除127.0.0.1:6379> ttl tkey(integer) -1

2、INCR/LPUSH/HSET等命令则不会清除过期时间

而在使用INCR/LPUSH/HSET这种只是修改一个key的value,而不是覆盖整个value的命令,则不会清除key的过期时间。

INCR:

//设置incr_key的过期时间为500s127.0.0.1:6379> set incr_key 1 ex 500OK127.0.0.1:6379> ttl incr_key(integer) 390//进行自增操作127.0.0.1:6379> incr incr_key(integer) 2127.0.0.1:6379> get incr_key"2"//查询过期时间,发现过期时间没有被清除127.0.0.1:6379> ttl incr_key(integer) 312

LPUSH:

//新增一个list类型的key,并添加一个为1的值127.0.0.1:6379> LPUSH list 1(integer) 1//为list设置500s的过期时间127.0.0.1:6379> expire list 500(integer) 1//查看过期时间127.0.0.1:6379> ttl list(integer) 392//往list里面添加值2127.0.0.1:6379> lpush list 2(integer) 2//查看list的所有值127.0.0.1:6379> lrange list 0 11) "2"2) "1"//能看到往list里面添加值并没有使过期时间清除127.0.0.1:6379> ttl list(integer) 352

3、PERSIST命令会清除过期时间

当使用PERSIST命令将一个设置了过期时间的key转变成一个持久化的key的时候,也会清除过期时间。

127.0.0.1:6379> set persist_key hello ex 400OK127.0.0.1:6379> ttl persist_key(integer) 396//将key变为持久化的127.0.0.1:6379> persist persist_key(integer) 1//过期时间被清除127.0.0.1:6379> ttl persist_key(integer) -1

4、使用RENAME命令,老key的过期时间将会转到新key上

在使用例如:RENAME KEY_1 KEY_2命令将KEY_1重命名为KEY_2,不管KEY_1有没有设置过期时间,新的key KEY_2将会继承KEY_1的所有特性。

//设置key_1的过期时间为400s127.0.0.1:6379> set key_1 value_1 ex 400OK//设置key_2的过期时间为500s127.0.0.1:6379> set key_2 value_2 ex 500OK127.0.0.1:6379> ttl key_1(integer) 379127.0.0.1:6379> ttl key_2(integer) 391//将key_1重命名为key_2127.0.0.1:6379> rename key_1 key_2OK//新的key_1继承了key_2的过期时间127.0.0.1:6379> ttl key_2(integer) 348

5、使用EXPIRE/PEXPIRE设置的过期时间为负数或者使用EXPIREAT/PEXPIREAT设置过期时间戳为过去的时间会导致key被删除

EXPIRE:

127.0.0.1:6379> set key_1 value_1OK127.0.0.1:6379> get key_1"value_1"//设置过期时间为-1127.0.0.1:6379> expire key_1 -1(integer) 1//发现key被删除127.0.0.1:6379> get key_1(nil)

EXPIREAT:

127.0.0.1:6379> set key_2 value_2OK127.0.0.1:6379> get key_2"value_2"//设置的时间戳为过去的时间127.0.0.1:6379> expireat key_2 10000(integer) 1//key被删除127.0.0.1:6379> get key_2(nil)

6、EXPIRE命令可以更新过期时间

对一个已经设置了过期时间的key使用expire命令,可以更新其过期时间。

//设置key_1的过期时间为100s127.0.0.1:6379> set key_1 value_1 ex 100OK127.0.0.1:6379> ttl key_1(integer) 95//更新key_1的过期时间为300s127.0.0.1:6379> expire key_1 300(integer) 1127.0.0.1:6379> ttl key_1(integer) 295

在Redis2.1.3以下的版本中,使用expire命令更新一个已经设置了过期时间的key的过期时间会失败。并且对一个设置了过期时间的key使用LPUSH/HSET等命令修改其value的时候,会导致Redis删除该key。

Redis的过期策略

如果Redis里面如果有大量的key,怎样才能高效的找出过期的key并将其删除,如果采用遍历的方式,假如同一时期过期的key非常多,Redis会不会因为一直处理过期事件,而导致读写指令的卡顿。

因为Redis是单线程的,所以一些耗时的操作会导致Redis卡顿,比如当Redis数据量特别大的时候,使用keys * 命令列出所有的key。

实际上Redis使用懒惰删除+定期删除相结合的方式处理过期的key。

1.懒惰删除

懒惰删除就是在客户端访问该key的时候,redis会对key的过期时间进行检查,如果过期了就立即删除。

这种方式看似很完美,在访问的时候检查key的过期时间,不会占用太多的额外CPU资源。但是如果一个key已经过期了,如果长时间没有被访问,那么这个key就会一直存留在内存之中,严重消耗了内存资源。

2.定期删除

定期删除的原理是,Redis会将所有设置了过期时间的key放入一个字典中,然后每隔一段时间从字典中随机一些key检查过期时间并删除已过期的key。

Redis默认每秒进行10次过期扫描:

(1)从过期字典中随机20个key
(2)删除这20个key中已过期的
(3)如果超过25%的key过期,则重复第一步

同时,为了保证不出现循环过度的情况,Redis还设置了扫描的时间上限,默认不会超过25ms。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。