熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除。

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

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

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

//设置mykey的过期时间为300s
127.0.0.1:6379> set mykey hello ex 300
OK
//查看过期时间
127.0.0.1:6379> ttl mykey
(integer) 294
//使用set命令覆盖mykey的内容
127.0.0.1:6379> set mykey olleh
OK
//过期时间被清除
127.0.0.1:6379> ttl mykey
(integer) -1

2、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

LPUSH:

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

3、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

4、使用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

这里篇幅有限,我就不一一将key_a重命名到key_b的各个情况列出来,大家可以在自己电脑上试一下key_a设置了过期时间,key_b没设置过期时间这种情况。

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

EXPIRE:

127.0.0.1:6379> set key_1 value_1
OK
127.0.0.1:6379> get key_1
"value_1"
//设置过期时间为-1
127.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_2
OK
127.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的过期时间为100s
127.0.0.1:6379> set key_1 value_1 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

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

Redis的过期策略

那你有没有想过一个问题,Redis里面如果有大量的key,怎样才能高效的找出过期的key并将其删除呢,难道是遍历每一个key吗?假如同一时期过期的key非常多,Redis会不会因为一直处理过期事件,而导致读写指令的卡顿。

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

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

懒惰删除

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

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

定期删除

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

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

  1. 从过期字典中随机20个key

  2. 删除这20个key中已过期的

  3. 如果超过25%的key过期,则重复第一步

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

在Redis中设置了过期时间的Key,需要注意哪些问题?的更多相关文章

  1. C# asp.net IIS 在web.config和IIS中设置Session过期时间

    有时候在web.config设置sessionState 或者类文件里设置Session.Timeout,在IIS里访问时每次都是达不到时间就超时,原因是因为在IIS中设置了Session的超时时间, ...

  2. asp中设置session过期时间方法总结

    http://www.jb51.net/article/31217.htm asp中设置session过期时间方法总结 作者: 字体:[增加 减小] 类型:转载   asp中默认session过期时间 ...

  3. spring boot整合redis,以及设置缓存过期时间

    spring-boot 整合 redis 注:redis服务器要先开启 pom文件: <dependency> <groupId>org.springframework.boo ...

  4. redis中获取没有设置ttl过期时间的key

    需求:redis作为一个内存型的数据库,我们需要对过期key保持关注,从info keyspace中可以看出有多少key没有设置过期时间,那么到底是哪些呢? 说明:关于redis ttl 的返回值,请 ...

  5. Java中设置Session过期时间(Spring Boot)

    1.Spring Boot: server.session.cookie.comment = #注释会话cookie. server.session.cookie.domain = #会话cookie ...

  6. java中设置session过期时间

    Web容器 apache-tomcat-8.0.26\conf\web.xml中设置 <session-config> <!-- 时间单位为分钟 --> <session ...

  7. 查询redis中没有设置过期时间的key

    #!/bin/sh ## 该脚本用来查询redis集群中,哪些key是没有设置过期时间,对应只需要修改redis的其中一个实例的 host和port ## 脚本会自动识别出该集群的所有实例,并查出对应 ...

  8. 关于web会话中的session过期时间的设置

    关于web会话中的session过期时间的设置 1.操作系统: 步骤:开始——〉管理工具——〉Internet信息服务(IIS)管理器——〉网站——〉默认网站——〉右键“属性”——〉主目录——〉配置— ...

  9. php中实现精确设置session过期时间的方法

    http://www.jb51.net/article/52309.htm 大多数据情况下我们对于session过期时间使用的是默认设置的时间,而对于一些有特殊要求的情况下我们可以设置一下sessio ...

随机推荐

  1. OSI七层模型与TCP/IP五层模型-(转自钛白Logic)

    OSI七层模型与TCP/IP五层模型         博主是搞是个FPGA的,一直没有真正的研究过以太网相关的技术,现在终于能静下心学习一下,希望自己能更深入的掌握这项最基本的通信接口技术.下面就开始 ...

  2. 【错误解决】Error creating bean with name 'transactionManager' :nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/

    搭建ssh框架中新建JUint测试出现的问题.这个问题实在太伤脑筋....因为不好找到解决办法 直接先说解决方式:添加org.springframework.jdbc-XX.jar,然后build p ...

  3. 简单读读源码 - dubbo多提供者(provider)配置方法

    简单读读源码 - dubbo多提供者(provider)配置方法 消费者端dubbo的yml配置 dubbo: consumer: timeout: 300000 protocol: name: du ...

  4. xshell 终端 中文乱码

    我们在终端输入命令,中文显示乱码了. 解决方案:将xshell 传输采用的默认encode改为utf-8 解决:

  5. SqlServer事务详解(事务隔离性和隔离级别详解)

    概述 不少人对于事务的使用局限于begin transaction:开始事务.commit transaction:提交事务.rollback transaction:回滚事务的初步运用. 并且知道使 ...

  6. week-01

    week-01 1. 计算机组成 从底层开始: 硬件: CPU.内存.硬盘.网卡.主板.显卡.风扇.电源.鼠标键盘 等: 系统: Linux.Windows.Mac 等: 软件: QQ.微信.吃鸡.农 ...

  7. 80个Python练手项目列表

    80个Python练手项目列表   我若将死,给孩子留遗言,只留一句话:Repetition is the mother of all learning重复是学习之母.他们将来长大,学知识,技巧.爱情 ...

  8. GO语言复合类型04---映射

    package main import "fmt" /* 映射(map)是键值对(key-value)数据的集合 根据键key可以快速检索值value 键值的类型可以是任意的,ke ...

  9. Jittor框架API

    Jittor框架API 这里是Jittor主模块的API文档,可以通过import jittor来获取该模块. classjittor.ExitHooks exc_handler(exc_type,  ...

  10. NVIDIA安倍架构

    NVIDIA安倍架构 NVIDIA Ampere ArchitectureNVIDIA The Heart of the World's Highest-Performing, Elastic Dat ...