设置键的生存时间或过期时间

通过EXPIRE 命令或者PEXPIRE 命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间( Time To Live , TTL) ,在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间为0的键:

redis> SET key value
OK
redis> EXP 工RE key 5
(integer) 1
redis> GET key // 5 秒之内
"value"
redis> GET key // 5 秒之后
(nil)

注意
SETEX 命令可以在设直一个字符串键的同时为键设直过期时间,因为这个命令是一个类型限定的命令(只能用于字符串键),但SETEX 命令设置过期时间的原理和EXPIRE命令设置过期时间的原理是完全一样的。

与EXPlRE 命令和PEXPIRE 命令类似,客户端可以通过EXPlREAT 命令或PEXPlREAT命令,以秒或者毫秒精度给数据库中的某个键设置过期时间(expire time)。
过期时间是一个UNIX时间戳,当键的过期时间来临时,服务器就会自动从数据库中删除这个键:

redis> SET key value
OK
redis> EXPIREAT key 1377257300
(integer) 1
redis> TIME1)"1377257296"
2)"296543"
redis> GET key // 1377257300 之前
"value"
redis> TIME
1)"1377257303"
2)"230656 "
redis> GET key // 1377257300 之后
(nil)

TTL 命令和PTTL 命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间,也就是,返回距离这个键被服务器自动删除还有多长时间:

redis> SET key va1ue
OK
redis> EXPlRE key 1000
(integer) 1
redis> TTL key
(integer) 997
redis> SET another_key another_value
OK
redis> TIME
1) "1377333070 "
2)  "761687 "
redis> EXPlREAT another key 1377333100
(integer ) 1
redis> TTL another key
(integer) 10

设置过期时间

Redis 有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除) :
EXPlRE <key> <ttl> 命令用于将键key 的生存时间设置为ttl 秒。
PEXPIRE <key> <ttl> 命令用于将键key 的生存时间设置为ttl 毫秒。
EXPIREAT <key> < timestamp> 命令用于将键key 的过期时间设置为timestamp所指定的秒数时间戳。
PEXPIREAT <key> < timestamp > 命令用于将键key 的过期时间设置为timestamp所指定的毫秒数时间戳。

虽然有多种不同单位和不同形式的设置命令,但实际上EXPlRE、PEXPlRE 、EXPIREAT三个命令都是使用PEXPlREAT 命令来实现的:无论客户端执行的是以上四个命令中的哪一个, 经过转换之后,最终的执行效果都和执行PEXPlREAT 命令一样。
首先, EXPIRE 命令可以转换成PEXPlRE 命令:

def EXPIRE(key,ttl_in_sec):
#将TTL 从秒转换成毫秒
ttl_in_ms = sec_to_ms(ttl_in_sec )
PEXPlRE(key, ttl_in_ms)

接着,PEXPlRE 命令又可以转换成PEXPlREAT 命令:

def PEXPIRE(key,ttl_in_ms) :
#获取以毫秒计算的当前UNIX 时间戳
now_ms = get_current_unix_timestamp_in_ms()
#当前时间加上TTL,得出毫秒格式的键过期时间
PEXPlREAT(key,now_ms+ttl_in_ms)

并且,EXPlREAT命令也可以转换成PEXPlREAT命令:

def EXPIREAT (key,expire_time_in_ sec):
#将过期时间从秒转换为毫秒
expire_time_ in_ms = sec_to_ms (expire_time_in_sec)
PEXPlREAT(key, expire_time_in_ms)

保存过期时间

redisDB结构的expires字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典:
过期字典的键是一个指针,这个指针指向键空间中的某个键对象( 也即是某个数据库键)。
过期字典的值是一个long long 类型的整数,这个整数保存了键所指向的数据库键的过期时间:一个毫秒精度的UNIX 时间戳。

typedef struct redisDb {
//...
// 过期字典,保存着键的过期时间dict *expires ;
//...
} redisDb;

如下图展示了一个带有过期字典的数据库例子,在这个例子中,键空间保存了数据库中的所有键值对,而过期字典则保存了数据库键的过期时间。

过期字典将新增一个键值对, 其中键为message 键对象,而值则为1391234400000(2014年2月1日零时) ,如图9-13 所示。

图9-12 中的过期字典保存了两个键值对:
第一个键值对的键为alphabet 键对象,值为1385877600000 ,这表示数据库键alphabet 的过期时间为1385877600000 (2013年12月1日零时)。
第二个键值对的键为book键对象,值为1388556000000,这表示数据库键book的过期时间为1388556000000(2014年1月1日零时)。
当客户端执行PEXPIREAT 命令(或者其他三个会转换成PEXPIREAT命令的命令)为一个数据库键设置过期时间时,服务器会在数据库的过期字典中关联给定的数据库键和过期时间。
举个例子, 如果数据库当前的状态如图9-12 所示, 那么在服务器执行以下命令之后:

redis> PEXPIREAT message 1 391234400000
(integer) 1

过期字典将新增一个键值对,其中键为message键对象,而值则为1391234400000(2014年2月1日零时),如图9-13 所示。

以下是PEXPlREAT 命令的伪代码定义:

def PEXPIREAT(key,expire_time_in_ms) :
#如果给定的键不存在于键空间,那么不能设置过期时间
if key not in redisDB.dict :
return 0
#在过期字典中关联键和过期时间
redisDB.expires[key]=expire_tirne_in_ms
#过期时间设置成功
return 1

移除过期时间

PERSIST命令可以移除一个键的过期时间:

redis>PEXPlREAT message 1391234400000
(integer) 1
redis>TTL message
(integer) 13893281
redis> PERSIST message
(integer) 1
redis> TTL message
(integer) - 1

PERSIST命令就是PEXPIREAT命令的反操作: PERSIST 命令在过期字典中查找给定的键,并解除键和值(过期时间)在过期字典中的关联。
举个例子,如果数据库当前的状态如图9-12所示,那么当服务器执行以下命令之后:

redis> PERSIST book
(integer) 1

数据库将更新成图9-14 所示的状态。

可以看到,当PERSIST命令执行之后,过期字典中原来的book键值对消失了,这代表数据库键book的过期时间已经被移除。
以下是PERSIST 命令的伪代码定义:

def PERSIST(key) :
#如果键不存在,或者键没有设置过期时间,那么直接返回
if key not in redisDB.expires:
return 0
#移除过期字典中给定键的键值对关联
redisDB.expires.remove(key)
#键的过期时间移除成功
return 1

计算并返回剩余生存时间

TTL 命令以秒为单位返回键的剩余生存时间, 而P TTL 命令则以毫秒为单位返回键的剩余生存时间:

redis> PEXPIREAT alphabet 1385877600000
(integer) 1
redis> TTL alphabet
(integer) 85 49007
redis> PTTL alphabet
(integer) 8549001011

TTL 和PTTL 两个命令都是通过计算键的过期时间和当前时间之间的差来实现的,以下
是这两个命令的伪代码实现:

def PTTL (key) :
#键不存在于数据库
if key not in redisDb.dict:
return -2
#尝试取得键的过期时间
#如果键没有设置过期时间,那么expire_time_in_ms将为None
expire_time_in_ms = redisDB.expires.get(key)
#键没有设置过期时间
if expire time in ms is None:
return -1
#获得当前时间
now_ms = get_current_unix _timestamp_in_ms ()
#过期时间减去当前时间, 得出的差就是键的剩余生存时间
return(expire_time_in_ms - now_ms)
def TTL(key):
#获取以毫秒为单位的剩余生存时间
ttl_in_ms = PTTL (key )
if ttl_in_ms < 0:
#处理返回值为2 和斗的情况
return ttl_in_ms
else:
#将毫秒转换为秒
return ms_to_sec(ttl_in_ms)

举个例子,对于一个过期时间为1385877600000(2013年12月1日零时)的键alphabet来说:
如果当前时间为1383282000000 (2013年11月1日零时),那么对键alphabet执行PTTL命令将返回2595600000 ,这个值是通过用a1phabet 键的过期时间减去当前时间计算得出的: 1385877600000-1383282000000=25956000000
另一方面,如果当前时间为1383282000000 ( 2013年11月1日零时),那么对键alphabet执行TTL命令将返回2595600,这个值是通过计算alphabet 键的过期时间减去当前时间的差,然后将差值从毫秒转换为秒之后得出的。

过期键的判定

通过过期字典,程序可以用以下步骤检查一个给定键是否过期:
1 )检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间。
2 )检查当前UNIX 时间戳是否大于键的过期时间: 如果是的话,那么键已经过期;否则的话,键未过期。
可以用伪代码来描述这一过程:

def is expired(key) :
#取得键的过期时间
expire_time_in_ms = redisDB.expires.get(key)
#键没有设置过期时间
if expire_time_in_ms is none:return false
#取得当前时间的UNIX 时间戳
now_ms = get_current_unix_timestamp_in_ms()
#检查当前时间是否大于键的过期时间
if now_ms > expire time_in_ms :
#是,键已经过期
return true
else :
# 否,键未过期
return false

举个例子,对于一个过期时间为1385877600000 (2013年12月1日零时)的键alphabet来说:

如果当前时间为1383282000000 (2013 年II 月1 日零时),那么调用is_expired ( alphabet ) 将返回False ,因为当前时间小于alphabet 键的过期时间。
另一方面,如果当前时间为1385964000000 (2013年12月2日零时),那么调用is_expired(alphabet) 将返回True. 因为当前时间大于alphabet 键的过期时间。

注意
实现过期键判定的另一种方法是使用TTL 命令或者PTTL 命令,比如说,如采对某个键执行TTL 命令,并且命令返回的位大于等于0 ,那么说明该键未过期。在实际中, Redis检查键是否过期的方法和is_expired函数所描述的方法一致,因为直接访问字典比执行一个命令稍微快一些。

redis设置键的生存时间或过期时间相关推荐

  1. Redis数据库-键的生存时间与过期时间的区别

    2019独角兽企业重金招聘Python工程师标准>>> 生存时间是一个时间值,表示从当前时间开始,经过多少秒过期: 过期时间是一个Unix时间戳,是一个时间点,比如2015-06-1 ...

  2. Redis 笔记(09)— 过期时间 expire(设置、查询、取消过期时间)

    1. 设置过期时间 Redis 使用 expire 命令设置一个键的过期时间,到时间后 Redis 会自动删除它.expire 命令的使用方法为 expire key seconds 其中 secon ...

  3. c# redis 如何设置过期时间_Spring cache整合Redis,并给它一个过期时间!

    小Hub领读: 不知道你们有没给cache设置过过期时间,来试试? 上一篇文章中,我们使用springboot集成了redis,并使用RedisTemplate来操作缓存数据,可以灵活使用. 我才懂! ...

  4. java redis expire 1_redis 下key的过期时间详解 :expire

    Redis是一个开源的Key-Value数据缓存,和Memcached类似. Redis多种类型的value,包括string(字符串).list(链表).set(集合).zset(sorted se ...

  5. Redis——过期时间/过期回收策略

    既然是缓存,就会涉及过期时间以及过期后清理回收内存的过程:本篇主要讲一下redis的key过期时间相关的命令.注意事项.回收策略: 注意:实际上,redis的内存回收触发有两种情况,上面说的是一种,也 ...

  6. redis map 过期时间_redis的过期时间和过期删除机制

    一:设置过期时间 redis有四种命令可以用于设置键的生存时间和过期时间: EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒 PEXPIRE <K ...

  7. Redis源码分析:过期key删除与设置key的过期时间

    Redis中设置key过期时间与过期key的处理流程 在Redis中,可以再设置值的时候就设置该Key的过期时间,也可以通过在expire命令来设置某个key值的过期时间,并且在了解完设置过期时间之后 ...

  8. java如何保证redis设置过期时间的原子性_分布式锁用 Redis 还是 Zookeeper

    在讨论这个问题之前,我们先来看一个业务场景: 系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户下单. 由于系统有 ...

  9. spring boot 缓存redis设置定时过期时间

    前言 本篇文章分享的就是spring boot中的一个轮子,spring cache注解的方式实现接口数据缓存.默认的配置想非常简单,但是有一个弊端是缓存数据为永久缓存,本次将介绍如何设置接口缓存数据 ...

最新文章

  1. 武汉理工java_Java语言程序设计E
  2. 【深度学习篇】--Windows 64下tensorflow-gpu安装到应用
  3. WindowManager.LayoutParams各种flag含义
  4. Java虚拟机13:Java类加载机制
  5. 事件标志组的等待与通知
  6. 运用贪心思想解决跳跃游戏
  7. python settings模块导入不了_python settings 中通过字符串导入模块
  8. Halo2 Map Editor Error
  9. svn上传文件最大多少_SVN控制上传文件尺寸
  10. cplex入门系列(二)--- 线性规划求解
  11. 动画七、动画的PropertyValuesHolder与Keyframe
  12. (附超声射频数据)matlab实现b超原始信号数据生成图像
  13. QCM2290平台XBL阶段I2C使能并点亮LED
  14. word中批注快速跳转
  15. CSUOJ-1986: 玄学
  16. 关于nbsp的一点笔记
  17. Mybatis中复杂语句标签的简单初步使用
  18. java 进销存C S_java 库存 进销存 商户 多用户管理系统 SSM springmvc 项目源码
  19. 等离子电视工作原理(转)
  20. 微服务架构下的根因定位方法综述

热门文章

  1. python的rsa公钥解密方法
  2. 关于实现Runnable接口的类中有公共属性问题
  3. 提升【百度网盘】下载速度
  4. vue-router 按需加载
  5. 1.4最基本的使用--POM.xml文件
  6. Maven入门指南② :Maven 常用命令,手动创建第一个 Maven 项目
  7. HTTP 返回状态消息讲解
  8. IBM DW上关于SOA的规范归纳
  9. StringBuffer 案例
  10. // 、| || 的区别