redis设置key过期时间,你可能误会他了

前言

之前在项目中某个功能用redis做限流,里面需要对Key设置1分钟的过期时间。请求进来的时候对这个key进行incr。在incr之前特意重新获取了这个key的过期时间,然后在incr之后,将刚刚获取的过期时间重新设置到这个key上。如果这个key过期之后,重新设置key初始值为1,过期时间设置为1分钟。这种写法咋看好像没啥问题,但是熟悉redis的小伙伴可能就觉得,在incr之后为什么要重新设置key为新的过期时间。其实在redis中对于incr确实不需要多次一举了,incr操作不会去清除这个key之前设置的过期时间。那么我为什么要多次一举呢,主要是因为把redis中的set操作和incr搞错了。redis对key设置新的值之后,key之前设置的过期时间会被清除,我以为incr操作也是如此,所以导致了这个问题。对于redis还是要认真去学习下那些细节,一知半解可不是什么好事,说不定哪天在就在项目中挖了个大坑。下面来和大家一起学习redis中对key设置过期的小知识。

具体小细节

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

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

//设置key的过期时间为150s
127.0.0.1:6379> set key hello ex 150
OK
127.0.0.1:6379> ttl key
(integer) 144  
//使用set命令覆盖key的内容
127.0.0.1:6379> set key aiqinhai
OK
//过期时间被清除
127.0.0.1:6379> ttl key
(integer) -1

可以看到ttl key的时候返回-1,说明这个key的过期时间已经被清楚,这里额外说下ttl返回-2,说明这个key不存在,不要搞串了。

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

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

//设置incr_key的过期时间为300s
127.0.0.1:6379> set incr_key 1 ex 300
OK
127.0.0.1:6379> ttl incr_key
(integer) 291
//进行自增操作
127.0.0.1:6379> incr incr_key
(integer) 2
127.0.0.1:6379> get incr_key
"2"
//查询过期时间,发现过期时间没有被清除
127.0.0.1:6379> ttl incr_key
(integer) 277

和上面的对比,显然可以看到之前设置的过期时间是有效的。

PERSIST命令会清除过期时间

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

127.0.0.1:6379> set persist_key haha ex 300
OK
127.0.0.1:6379> ttl persist_key
(integer) 296
//将key变为持久化的
127.0.0.1:6379> persist persist_key
(integer) 1
//过期时间被清除
127.0.0.1:6379> ttl persist_key
(integer) -1

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

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

//设置key_a的过期时间为300s
127.0.0.1:6379> set key_a value_a ex 300
OK
//设置key_b的过期时间为600s
127.0.0.1:6379> set key_b value_b ex 600
OK
127.0.0.1:6379> ttl key_a
(integer) 279
127.0.0.1:6379> ttl key_b
(integer) 591
//将key_a重命名为key_b
127.0.0.1:6379> rename key_a key_b
OK
//新的key_b继承了key_a的过期时间
127.0.0.1:6379> ttl key_b
(integer) 248

使用EXPIRE/PEXPIRE设置的过期时间为负数会导致key被删除

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

EXPIREAT设置过期时间为过去时间也是如此,这里不做演示了。

EXPIRE命令可以更新过期时间

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

//设置key_1的过期时间为100s
127.0.0.1:6379> set key_1 aiqinhai ex 100
OK
127.0.0.1:6379> ttl key_1
(integer) 95
//更新key_1的过期时间为300s
127.0.0.1:6379> expire key_1 300
(integer) 1
127.0.0.1:6379> ttl key_1
(integer) 295

总结

上面大致介绍了redis设置超时时间一些小细节,这些小细节不搞清楚,往往就是一个大雷,抑或在测试那就是一个bug。

参考文献

https://juejin.im/post/5d6bda096fb9a06acc009dc8#comment

你可能感兴趣的:(redis过期时间,redis)