赶知识网

Redis设置过期时间要注意的问题

2023-12-14 / 254次点击 php/mysql/apache redis

今天给大家分享的是Redis基础命令set过期时间被覆盖问题。该命令可能是大家最为常见的一个命令,但有一个小细节可能很多人多都没注意到,今天就来演示总结一下。

该细节虽然看着很小,平常也很少关注到这点。但在实际的生产环境发生过一次,对于一些流量大的应用尤其需要注意。

场景演示

首先我们按照常规的操作,向Redis中插入一个值。示例代码如下:

127.0.0.1:6379> set demo kert ex 100OK127.0.0.1:6379> ttl demo(integer) 87

上面的命令不难看出,向Redis中插入了一个string类型的值,key为demo,值为kert,并且为其设置了一个过期时间。

接下来,我们对该key进行重新设值(update操作)。

127.0.0.1:6379> set demo bruce
OK

看到这里,我们先思考3秒钟,该key的过期时间是多少?

  • 过期时间可能是第一次设置时间

  • 永不过期

带着这两种疑问,我们看看实际的结果。

127.0.0.1:6379> ttl demo(integer) -1

实际上结果变成了-1。-1是什么意思呢,在Redis中要查看某个key的过期时间,我们可以使用ttl命令。它会返回三种可能的值:

  • 如果为 >= 0 则是该key的剩余过期时间,返回的时间是秒(s),如果想返回毫秒,可以使用pttl

  • 如果为 -1 则是该key没有设置过期时间

  • 如果为 -2 则是该key不存在,可能是本身就不存在也有可能是该key已到过期时间,被Redis标记为过期的key

通过实际的演示,我们返现使用set命令时,会覆盖原本key的过期时间,并且将该key设置为永久不失效的key。

解决方案

要保持该key的过期时间,这里有两种方案:

  • 先获取该key的过期时间,如果设置了过期时间,重新赋值之后再对其设置过期时间

  • 使用Redis6.0版本之后的新命令参数,keepttl

第一种方案

示例代码如下:

127.0.0.1:6379> set demo bruce ex 100OK127.0.0.1:6379> ttl demo(integer) 96127.0.0.1:6379> set demo 7small7
OK127.0.0.1:6379> ttl demo(integer) -1127.0.0.1:6379> expire demo 96(integer) 1127.0.0.1:6379> ttl demo(integer) 93

上述代码,大致的逻辑就是先设置一个带过期时间的key,并且在重新赋值前,获取过期时间,重新赋值之后再对key设置原来的过期时间。

该方式有2个大的问题,过期key的时间差,以及多个命令执行的原子性。

第二种方案

上述第1种的解决方案存在两个问题,接下来我们使用官方提供的命令参数。

127.0.0.1:6379> set demo bruce ex 100OK127.0.0.1:6379> ttl demo(integer) 96127.0.0.1:6379> set demo 1111 keepttl
OK127.0.0.1:6379> ttl demo(integer) 82

通过上面的操作,可以看到key的过期时间还是原有的过期时间。并且命令属于原子性操作,不用担心某个命令操作失败的问题。

最后还需要注意一点:官方原本提供了SETNX, SETEX, PSETEX, GETSET等命令,但现在官方推荐不要使用这样的命令,在将来这些命令可能会被移除,而推荐是SET命令+参数的方式来实现。

Note: Since the SET command options can replace SETNX, SETEX, PSETEX, GETSET, it is possible that in future versions of Redis these commands will be deprecated and finally removed.


有用 没用

Top10

沪ICP备09053415号 © 赶知识网