Redis中键值过期操作示例详解

1.过期设置

Redis 中设置过期时间主要通过以下四种方式:

  • expire key seconds:设置 key 在 n 秒后过期;
  • pexpire key milliseconds:设置 key 在 n 毫秒后过期;
  • expireat key timestamp:设置 key 在某个时间戳(精确到秒)之后过期;
  • pexpireat key millisecondsTimestamp:设置 key 在某个时间戳(精确到毫秒)之后过期;

下面分别来看以上这些命令的具体实现。

1)expire:N 秒后过期

127.0.0.1:6379> set key value
OK
127.0.0.1:6379> expire key 100
(integer) 1
127.0.0.1:6379> ttl key
(integer) 97

其中命令 ttl 的全称是 Time To Live 表示此键值在 n 秒后过期。例如,上面的结果 97 表示 key 在 97s 后过期。

2)pexpire:N 毫秒后过期

127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> pexpire key2 100000
(integer) 1
127.0.0.1:6379> pttl key2
(integer) 94524

其中 pexpire key2 100000 表示设置 key2 在 100000 毫秒(100秒)后过期。

3)expireat:过期时间戳精确到秒

127.0.0.1:6379> set key3 value3
OK
127.0.0.1:6379> expireat key3 1573472683
(integer) 1
127.0.0.1:6379> ttl key3
(integer) 67

其中 expireat key3 1573472683 表示 key3 在时间戳 1573472683 后过期(精确到秒),使用 ttl 查询可以发现在 67s 后 key3 会过期。

小贴士:在 Redis 可以使用 time 命令查询当前时间的时间戳(精确到秒),示例如下:
127.0.0.1:6379> time
1) "1573472563"
2) "248426"

4)pexpireat:过期时间戳精确到毫秒

127.0.0.1:6379> set key4 value4
OK
127.0.0.1:6379> pexpireat key4 1573472683000
(integer) 1
127.0.0.1:6379> pttl key4
(integer) 3522

其中 pexpireat key4 1573472683000 表示 key4 在时间戳 1573472683000 后过期(精确到毫秒),使用 ttl 查询可以发现在 3522ms 后 key4 会过期。

5)字符串中的过期操作

字符串中几个直接操作过期时间的方法,如下列表:

  • set key value ex seconds:设置键值对的同时指定过期时间(精确到秒);
  • set key value ex milliseconds:设置键值对的同时指定过期时间(精确到毫秒);
  • setex key seconds valule:设置键值对的同时指定过期时间(精确到秒)。

实现示例如下:

① set key value ex seconds

127.0.0.1:6379> set k v ex 100
OK
127.0.0.1:6379> ttl k
(integer) 97

② set key value ex milliseconds

127.0.0.1:6379> set k2 v2 px 100000
OK
127.0.0.1:6379> pttl k2
(integer) 92483

③ setex key seconds valule

127.0.0.1:6379> setex k3 100 v3
OK
127.0.0.1:6379> ttl k3
(integer) 91

2.移除过期时间

使用命令: persist key 可以移除键值的过期时间,如下代码所示:

127.0.0.1:6379> ttl k3
(integer) 97
127.0.0.1:6379> persist k3
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -1

可以看出第一次使用 ttl 查询 k3 会在 97s 后过期,当使用了 persist 命令之后,在查询 k3 的存活时间发现结果是 -1,它表示 k3 永不过期。

3.Java实现过期操作

本文将使用 Jedis 框架来实现对 Redis 过期时间的操作,如下代码所示:

public class TTLTest {
 public static void main(String[] args) throws InterruptedException {
 // 创建 Redis 连接
 Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
 // 设置 Redis 密码(如果没有密码,此行可省略)
 jedis.auth("xxx");
 // 存储键值对(默认情况下永不过期)
 jedis.set("k", "v");
 // 查询 TTL(过期时间)
 Long ttl = jedis.ttl("k");
 // 打印过期日志
 System.out.println("过期时间:" + ttl);
 // 设置 100s 后过期
 jedis.expire("k", 100);
 // 等待 1s 后执行
 Thread.sleep(1000);
 // 打印过期日志
 System.out.println("执行 expire 后的 TTL=" + jedis.ttl("k"));
 }
}

程序的执行结果为:

过期时间:-1
执行 expire 后的 TTL=99

可以看出使用 Jedis 来操作 Redis 的过期时间还是很方便的,可直接使用 jedis.ttl("k") 查询键值的生存时间,使用 jedis.expire("k",seconds) 方法设置过期时间(精确到秒)。

小贴士:使用 Jedis 之前,先要把 Jedis 引入到程序中,如果使用的是 Maven 项目的,直接在 pom.xml 文件中添加以下引用:

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 <version>version</version>
</dependency>

更多过期操作方法,如下列表:

  • pexpire(String key, long milliseconds):设置 n 毫秒后过期;
  • expireAt(String key, long unixTime):设置某个时间戳后过期(精确到秒);
  • pexpireAt(String key, long millisecondsTimestamp):设置某个时间戳后过期(精确到毫秒);
  • persist(String key):移除过期时间。

完整示例代码如下:

public class TTLTest {
 public static void main(String[] args) throws InterruptedException {
 // 创建 Redis 连接
 Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
 // 设置 Redis 密码(如果没有密码,此行可省略)
 jedis.auth("xxx");
 // 存储键值对(默认情况下永不过期)
 jedis.set("k", "v");
 // 查询 TTL(过期时间)
 Long ttl = jedis.ttl("k");
 // 打印过期日志
 System.out.println("过期时间:" + ttl);
 // 设置 100s 后过期
 jedis.expire("k", 100);
 // 等待 1s 后执行
 Thread.sleep(1000);
 // 打印过期日志
 System.out.println("执行 expire 后的 TTL=" + jedis.ttl("k"));
 // 设置 n 毫秒后过期
 jedis.pexpire("k", 100000);
 // 设置某个时间戳后过期(精确到秒)
 jedis.expireAt("k", 1573468990);
 // 设置某个时间戳后过期(精确到毫秒)
 jedis.pexpireAt("k", 1573468990000L);
 // 移除过期时间
 jedis.persist("k");
 }
}

4.持久化中的过期键

上面我们讲了过期键在 Redis 正常运行中一些使用案例,接下来,我们来看 Redis 在持久化的过程中是如何处理过期键的。

Redis 持久化文件有两种格式:RDB(Redis Database)和 AOF(Append Only File),下面我们分别来看过期键在这两种格式中的呈现状态。

1)RDB中的过期键

RDB 文件分为两个阶段,RDB 文件生成阶段和加载阶段。

① RDB 文件生成

从内存状态持久化成 RDB(文件)的时候,会对 key 进行过期检查,过期的键不会被保存到新的 RDB 文件中,因此 Redis 中的过期键不会对生成新 RDB 文件产生任何影响。

② RDB 文件加载

RDB 加载分为以下两种情况:

  • 如果 Redis 是主服务器运行模式的话,在载入 RDB 文件时,程序会对文件中保存的键进行检查,过期键不会被载入到数据库中。所以过期键不会对载入 RDB 文件的主服务器造成影响;
  • 如果 Redis 是从服务器运行模式的话,在载入 RDB 文件时,不论键是否过期都会被载入到数据库中。但由于主从服务器在进行数据同步时,从服务器的数据会被清空。所以一般来说,过期键对载入 RDB 文件的从服务器也不会造成影响。

RDB 文件加载的源码可以在 rdb.c 文件的 rdbLoad() 函数中找到,源码所示:

/* Check if the key already expired. This function is used when loading
* an RDB file from disk, either at startup, or when an RDB was
* received from the master. In the latter case, the master is
* responsible for key expiry. If we would expire keys here, the
* snapshot taken by the master may not be reflected on the slave.
*
* 如果服务器为主节点的话,
* 那么在键已经过期的时候,不再将它们关联到数据库中去
*/
if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {
 decrRefCount(key);
 decrRefCount(val);
 // 跳过
 continue;
}

2)AOF中的过期键

① AOF 文件写入

当 Redis 以 AOF 模式持久化时,如果数据库某个过期键还没被删除,那么 AOF 文件会保留此过期键,当此过期键被删除后,Redis 会向 AOF 文件追加一条 DEL 命令来显式地删除该键值。

② AOF 重写

执行 AOF 重写时,会对 Redis 中的键值对进行检查已过期的键不会被保存到重写后的 AOF 文件中,因此不会对 AOF 重写造成任何影响。

5.主从库的过期键

当 Redis 运行在主从模式下时,从库不会进行过期扫描,从库对过期的处理是被动的。也就是即时从库中的 key 过期了,如果有客户端访问从库时,依然可以得到 key 对应的值,像未过期的键值对一样返回。

从库的过期键处理依靠主服务器控制,主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的 key。

6.小结

本文我们知道了 Redis 中的四种设置过期时间的方式:expire、pexpire、expireat、pexpireat,其中比较常用的是 expire 设置键值 n 秒后过期。

字符串中可以在添加键值的同时设置过期时间,并可以使用 persist 命令移除过期时间。同时我们也知道了过期键在 RDB 写入和 AOF 重写时都不会被记录。

过期键在主从模式下,从库对过期键的处理要完全依靠主库,主库删除过期键之后会发送 del 命令给所有的从库。

本文的知识点,如下图所示:

7.引用&鸣谢

https://www.jb51.net/article/174204.htm

https://www.jb51.net/article/174207.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Redis 不使用 keys 命令获取键值信息的方法

    1. 问题来源 这个问题可能看起来很奇怪,但很多 redis 集群会有一个统一的入口,入口会作兼容 redis 命令的代理,一般出于新能考虑是禁止使用 keys 命令来获取键值信息的,但是可以通过 scan 命令来代替 keys 2. 使用 keys 的方法 127.0.0.1:6379> KEYS * 1) "_kombu.binding.test_queue" 2) "a8e620b9-e52e-3498-8a1c-448f35783058" 3) &qu

  • Redis使用Eval多个键值自增的操作实例

    在PHP上使用Redis 给多个键值进行自增,示例如下: $set['money'] = $this->redis->hIncrByFloat($key, $hour .'_money', $data['money']); $set['ip'] = $this->redis->hIncrBy($key, $hour .'_ip', $data['ip']); $set['uv'] = $this->redis->hIncrBy($key, $hour .'_uv', $

  • Redis中键值过期操作示例详解

    1.过期设置 Redis 中设置过期时间主要通过以下四种方式: expire key seconds:设置 key 在 n 秒后过期: pexpire key milliseconds:设置 key 在 n 毫秒后过期: expireat key timestamp:设置 key 在某个时间戳(精确到秒)之后过期: pexpireat key millisecondsTimestamp:设置 key 在某个时间戳(精确到毫秒)之后过期: 下面分别来看以上这些命令的具体实现. 1)expire:N

  • Redis中键和数据库通用指令详解

    目录 一.Redis键(key)通用指令 1.key基本操作 2.时效性控制 3.查询模式 4.其它操作 二.数据库通用指令 1.基本操作 2.相关操作 一.Redis键(key)通用指令 可以参考菜鸟教程:Redis 键命令用于管理 redis 的键 key特征:key是一个字符串,通过key获取redis中保存的数据. 1.key基本操作 命令 功能 del key 该命令用于在 key 存在时删除 key exists key 检查给定 key 是否存在 type key 返回 key 所

  • Pandas读存JSON数据操作示例详解

    目录 引言 读取json数据 模拟数据 参数orident orident="split" orient="records" orient="index" orient="columns" orient="values" to_json 引言 本文介绍的如何使用Pandas来读取各种json格式的数据,以及对json数据的保存 读取json数据 使用的是pd.read_json函数,见官网:pandas.p

  • Java中Properties类的操作实例详解

    Java中Properties类的操作实例详解 知识学而不用,就等于没用,到真正用到的时候还得重新再学.最近在看几款开源模拟器的源码,里面涉及到了很多关于Properties类的引用,由于Java已经好久没用了,而这些模拟器大多用Java来写,外加一些脚本语言Python,Perl之类的,不得已,又得重新拾起.本文通过看<Java编程思想>和一些网友的博客总结而来,只为简单介绍Properties类的相关操作.  一.Java Properties类 Java中有个比较重要的类Properti

  • Go语言中的字符串处理方法示例详解

    1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号("")或反引号(``)定义. 双引号:"", 用于单行字符串. 反引号:``,用于定义多行字符串,内部会原样解析. 示例: // 单行 "心有猛虎,细嗅蔷薇" // 多行 ` 大风歌 大风起兮云飞扬. 威加海内兮归故乡. 安得猛士兮守四方! ` 字符串支持转义

  • TensorFlow人工智能学习张量及高阶操作示例详解

    目录 一.张量裁剪 1.tf.maximum/minimum/clip_by_value() 2.tf.clip_by_norm() 二.张量排序 1.tf.sort/argsort() 2.tf.math.topk() 三.TensorFlow高阶操作 1.tf.where() 2.tf.scatter_nd() 3.tf.meshgrid() 一.张量裁剪 1.tf.maximum/minimum/clip_by_value() 该方法按数值裁剪,传入tensor和阈值,maximum是把数

  • GO文件创建及读写操作示例详解

    目录 三种文件操作比较 ioutil ioutil.ReadFile读 ioutil.WriteFile 写 ioutil.ReadAll 读 ioutil.ReadDir 查看路径下目录信息 ioutil.TempDir 创建临时目录 ioutil.TempFile 创建临时文件 os.file 方法 os.OpenFile() 创建文件 写入数据三种方式 第一种-WriteString( )函数 第二种-Write( )函数 第三种-WriteAt( )函数 读取文件 Read 读取文件 按

  • RxJS中的Observable和Observer示例详解

    目录 引言 概念 牛刀小试 Observable Observable 剖析 Observer 结束语 引言 最近在项目当中别的小伙伴使用到了Rxjs,我一眼看上去有点懵,感觉挺复杂,挺绕的.于是抓紧补补课,然后就可以和小伙伴们一起交流怎么能优雅的使用Rxjs.由于内容比较多,会分为三篇来讲解说明 初识 RxJS中的 Observable 和 Observer 细说 RxJS中的 Operators 在谈 RxJS中的 Subject和Schedulers 概念 RxJS是一个库,可以使用可观察

  • react中使用antd及immutable示例详解

    目录 一.react中使用antd组件库 二.Immutable 2.1 深拷贝和浅拷贝的关系 2.2 immutable优化性能方式 2.3 immutable的Map使用 2.4 immutable的List使用 2.5 实际场景formJS 三.redux中使用immutable 一.react中使用antd组件库 运行命令create-react-app antd-react创建新项目: 运行命令npm i antd安装: 使用: import React from 'react' im

  • flutter中使用流式布局示例详解

    目录 简介 Flow和FlowDelegate Flow的应用 总结 简介 我们在开发web应用的时候,有时候为了适应浏览器大小的调整,需要动态对页面的组件进行位置的调整.这时候就会用到flow layout,也就是流式布局. 同样的,在flutter中也有流式布局,这个流式布局的名字叫做Flow.事实上,在flutter中,Flow通常是和FlowDelegate一起使用的,FlowDelegate用来设置Flow子组件的大小和位置,通过使用FlowDelegate.paintChildre可

随机推荐