熟悉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. 在 Kubernetes 集群在线部署 KubeSphere

    https://github.com/kubesphere/ks-installer/blob/master/README_zh.md https://kubesphere.com.cn/docs/i ...

  2. 使用Python操作InfluxDB时序数据库

    使用Python操作InfluxDB时序数据库 安装python包 influxdb,这里我安装的是5.3.0版本 pip install influxdb==5.3.0   使用 from infl ...

  3. python批量向kafka塞数据

    python批量向kafka塞数据 from kafka import KafkaClient from kafka.producer import SimpleProducer from kafka ...

  4. GO语言面向对象08---投胎游戏

    package main import ( "fmt" "math/rand" "os" "time" ) /* @内存 ...

  5. 树莓派3B+常用操作

    安装Docker 替换成清华源 清华源地址https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/ echo "deb [arch=armhf ...

  6. 在NVIDIA A100 GPU中使用DALI和新的硬件JPEG解码器快速加载数据

    在NVIDIA A100 GPU中使用DALI和新的硬件JPEG解码器快速加载数据 如今,最流行的拍照设备智能手机可以捕获高达4K UHD的图像(3840×2160图像),原始数据超过25 MB.即使 ...

  7. 中继TensorRT集成

    中继TensorRT集成 介绍 NVIDIA TensorRT是用于优化深度学习推理的库.这种集成将使尽可能多的算子从Relay转移到TensorRT,从而无需调整调度,即可在NVIDIA GPU上提 ...

  8. AMD–7nm “Rome”芯片SOC体系结构,支持64核

    AMD–7nm "Rome"芯片SOC体系结构,支持64核 AMD Fully Discloses Zeppelin SOC Architecture Details at ISS ...

  9. Excel创建手机号1000个

    一.输入手机号15900000001,并且选择 二.选中这一列 三.按住Ctrl,鼠标选中创建手机号,取消选中的状态 四.开始-填充 五.选择序列 六.选择列-自动填充-点击确定 七.查看结果,生成成 ...

  10. 三、使用sudo分配管理权限

    使用sudo分配管理权限 su命令 su -  [账户名称]     :切换到用户,不加用户名默认切换到root su -  [账户名称]  -c  '命令'   :以xx用户身份执行命令,注意命令需 ...