当前位置: 首页 > 科技观察

Redis中设置带过期时间的key需要注意哪些问题?

时间:2023-03-13 17:45:26 科技观察

熟悉Redis的同学应该都知道,Redis的每个key都可以设置过期时间。当达到过期时间时,密钥将被自动删除。设置key过期时间需要注意的事项1.DEL/SET/GETSET等命令会清除过期时间。当使用DEL、SET、GETSET等会覆盖key对应值的命令操作设置了过期时间的key时,会导致对应key的过期时间被清除。//设置mykey的过期时间为300s127.0.0.1:6379>setmykeyhelloex300OK//查看过期时间127.0.0.1:6379>ttlmykey(integer)294//使用set命令覆盖mykey的内容127.0.0.1:6379>setmykeyollehOK//expirationtimeiscleared127.0.0.1:6379>ttlmykey(integer)-12INCR/LPUSH/HSET等命令不会清除过期时间,使用INCR/LPUSH/HSET修改某个key的值insteadof覆盖整个值的命令不会清除键的过期时间。INCR://设置incr_key的过期时间为300s127.0.0.1:6379>setincr_key1ex300OK127.0.0.1:6379>ttlincr_key(integer)291//进行自增操作127.0.0.1:6379>incrincr_key(integer)2127.0.0.1:6379>getincr_key"2"//查询过期时间,发现过期时间没有清零127.0.0.1:6379>ttlincr_key(integer)277LPUSH://添加一个list类型的key,并添加一个值为1127.0。0.1:6379>LPUSHlist1(integer)1//设置list过期时间300s127.0.0.1:6379>expirelist300(integer)1//检查过期时间127.0.0.1:6379>ttllist(integer)292//IntothelistAddvalue2127.0.0.1:6379>lpushlist2(integer)2//查看list中的所有值127.0.0.1:6379>lrangelist011)"2"2)"1"//可以看到添加值对列表没有过期时间清除127.0.0.1:6379>ttllist(integer)2523.PERSIST命令会清除过期时间。当使用PERSIST命令将设置了过期时间的key转换为持久化key时,过期时间也会被清除。127.0.0.1:6379>setpersist_keyhahaex300OK127.0.0.1:6379>ttlpersist_key(integer)296//密钥持久化127.0.0.1:6379>persistpersist_key(integer)1//过期时间清空127.0.0.1:6379>ttlpersist_key(整数)-14。使用RENAME命令,旧密钥的到期时间将转移到新密钥。例如:RENAMEKEY_AKEY_B命令会将KEY_A重命名为KEY_B,无论KEY_B是否设置过期时间,新密钥KEY_B将继承KEY_A的所有特性。//设置key_a的过期时间为300s127.0.0.1:6379>setkey_avalue_aex300OK//设置key_b的过期时间为600s127.0.0.1:6379>setkey_bvalue_bex600OK127.0.0.1:6379>ttlkey_a(integer)279127.0.0.1:6379>ttlkey_b(integer)591//将key_a重命名为key_b127.0.0.1:6379>renamekey_akey_bOK//新的key_b继承key_a的过期时间127.0.0.1:6379>ttlkey_b(integer)248这里的篇幅有限,所以我就不一一列举key_a改名为key_b的情况了,大家可以在自己的电脑上试试,key_a设置了过期时间,而key_b没有过期时间。5、使用EXPIRE/PEXPIRE设置过期时间为负数或者使用EXPIREAT/PEXPIREAT设置过期时间戳为过去的时间都会导致key被删除EXPIRE:127.0.0.1:6379>setkey_1value_1OK127.0.0.1:6379>getkey_1"value_1"//设置过期时间为-1127.0.0.1:6379>expirekey_1-1(integer)1//发现key被删除127.0.0.1:6379>getkey_1(nil)EXPIREAT:127.0.0.1:6379>setkey_2value_2OK127.0.0.1:6379>getkey_2"value_2"//设置时间戳为过去时间127.0.0.1:6379>expireatkey_210000(integer)1//key被删除127.0.0.1:6379>getkey_2(nil)6、EXPIRE命令可以更新过期时间对设置过期时间的key使用expire命令更新其过期时间。//设置key_1的过期时间为100s127.0.0.1:6379>setkey_1value_1ex100OK127.0.0.1:6379>ttlkey_1(integer)95//更新key_1的过期时间为300s127.0.0.1:6379>expirekey_1300(integer)1127.0.0.1:6379>ttlkey_1(integer)295在Redis2.1.3以下版本,使用expire命令更新设置了过期时间的key的过期时间会失败。并且当使用LPUSH/HSET等命令修改设置了过期时间的key的值时,会导致Redis删除该key。Redis过期策略大家有没有想过一个问题,如果Redis中有大量的key,如何高效的找出过期的key并删除,是不是遍历每一个key?如果同一时期过期的key有这么多,Redis会不会因为一直在处理过期事件而冻结读写指令。这里说明一下,Redis是单线程的,所以一些耗时的操作会导致Redis卡死。比如当Redis的数据量特别大的时候,使用keys*命令列出所有的key。实际上,Redis是采用惰性删除和定时删除相结合的方式来处理过期键的。懒删除所谓懒删除,就是当客户端访问key时,redis会检查key的过期时间,如果过期就立即删除。这个方法看起来很完美。访问时检查key的过期时间不会额外占用过多的CPU资源。但是如果一个key已经过期,如果长时间没有被访问,那么这个key就会一直留在内存中,严重消耗内存资源。周期性删除周期性删除的原理是Redis会把所有设置了过期时间的key放入一个字典中,然后每隔一定时间从字典中随机取一些key检查过期时间,删除过期的key。默认情况下,Redis每秒执行10次过期扫描:从过期字典中随机删除20个键。如果超过25%的密钥已过期,请重复第一步。同时,为了保证不出现超循环,Redis还设置了扫描时间的上限,默认不会超过25ms。参考https://redis.io/commands/expire#expire-accuracy