Redis 的命令详解 - Key 篇

2,721 阅读9分钟

相关文章

Redis 的命令详解 - String 篇
Redis 的命令详解 - Hash 篇
Redis 的命令详解 - List 篇
Redis 的命令详解 - SET 篇
Redis 的命令详解 - Sorted Set 篇

Key 的命令详解

跟 key 相关的命令一共有 24 种,这里只介绍常用的。想查看全部命令请参考官网

KEYS : 查找 key

起始版本 : 1.0.0
时间复杂度 : O(N),其中N为数据库中密钥的数目。尽管操作的时间复杂度为O(N),但恒定时间却很短。例如,运行在入门级笔记本电脑上的Redis可以在40毫秒内扫描一百万个key。

注意:`KEYS` 命令,在生产环境中使用时要格外小心。在大型数据库上执行时,可能会影响性能。此命令用于调试和特殊操作,例如更改键空间布局。不要在常规应用程序代码中使用`KEYS`。如果您正在寻找一种在键空间的子集中查找键的方法,请考虑使用`SCAN`或`sets`。

语法

KEYS pattern

redis pattern 支持以下通配符

  • ? : 匹配单个字符
  • * : 匹配0到多个字符
  • [a-c] : 匹配a和c
  • [ac] : 匹配a到c
  • [^a] : 匹配除了a以外的字符

返回值

匹配的key的列表

DEL : 删除 key

起始版本 : 1.0.0
时间复杂度 : O(N),其中N是将被删除的key的数量。当要删除的key的value不是字符串类型时,此key的单个复杂度为O(M),其中M是列表、集合、有序集合或哈希中元素的数量。删除包含字符串值的单个key的复杂度为O(1)

不存在的 key 会被忽略。(删除 key 后,对应的 value 也会被删除)

语法

DEL key1 [key2 ...]

返回值

被删除 key 的数量。

UNLINK : 异步删除 key

起始版本 : 4.0.0
时间复杂度:对于每个被移除的key,无论其大小,时间复杂度都是O(1)。然后命令在不同的线程中执行回收内存的时间复杂度是O(N),其中N是被删除对象的分配数

UNLINKDEL 命令一样,用于删除 key,区别是 UNLINK 命令在另一个线程中执行内存回收,因此不会阻塞。

UNLINK 只是将key与key空间链接断开,实际的删除在稍后异步发生。(这也是它名称的来历)

语法

UNLINK key1 [key2 ...]

返回值

异步删除 key 的数量。

说明

不存在的 key 会被忽略。(删除 key 后,对应的 value 也会被删除)

EXISTS : 查看 key 是否存在

起始版本 : 1.0.0
时间复杂度 : O(1)

从Redis 3.0.3开始,可以指定多个key

语法

EXISTS key1 [key2 ...]

返回值

  • 指定单个key时,返回1或0
  • 指定多个key时,返回现有key的总数
  • 多个 key 相同时,会重复计数。例如 EXISTS somekey 返回1,EXISTS somekey somekey 返回2

TYPE : 查看 key 的 value 类型

起始版本 : 1.0.0
时间复杂度 : O(1)

语法

TYPE key

返回值

  • key 不存在时,返回 none
  • key 存在时,返回 value 对应的类型名称。如string、list、set、zset、 hash、stream

RENAME : 重命名 key

起始版本 : 1.0.0
时间复杂度 : O(1)

如果 newkey 已存在,这时 RENAME 会执行隐式 DEL 操作。即先删掉已存在的 newkey 再把 key 改名成 newkey。如果删除的键包含非常大的值,也可能导致高延迟。

语法

RENAME key newkey

返回值

  • key不存在时返回错误
  • 在Redis 3.2.0之前,如果源名称和目标名称相同,则会返回错误
  • 修改成功,返回ok

RENAMENX : 安全重命名 key

起始版本 : 1.0.0
时间复杂度 : O(1)

比起 RENAME 可能会隐式删除 keyRENAMENX 在重名名前会先判断 newkey 是否存在,如果存在就不重命名。

语法

RENAMENX key newkey

返回值

  • 1:key已重命名为newkey
  • 0:newkey已经存在
  • 在Redis 3.2.0之前,如果源名称和目标名称相同,则会返回错误
  • key 不存在,返回错误

EXPIRE : 给 key 设置生存时间,精确到秒

起始版本 : 1.0.0
时间复杂度 : O(1)

Redis 中,带有生存时间的 key 被称为 volatile (易丢失)。
key 过期时(生存时间为 0 ),它会被自动删除。

语法

EXPIRE key 秒

返回值

设置成功返回 1 。
当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。

说明

有些命令会对 key 的生存时间产生影响

  • DEL 命令会删除 keykey 不存在了,生存时间也会被移除
  • PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个持久的key 。
  • SETGETSET 命令 可以覆写 key生存时间

如果一个命令只是修改 key 的值而不是用一个新的 key 值来代替它的话,那么生存时间不会被改变。

例如,以下操作都不会修改 key 本身的生存时间。

  • 对一个 key 执行 INCR 命令
  • 对一个列表进行 LPUSH 命令
  • 或者对一个哈希表执行 HSET 命令

如果使用 RENAME 命令对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。这句话也适用于以下特殊情况。

假如有个两个带生存时间的 key。

  • 第一个key:名称为 name1 生存时间为 10秒
  • 第二个key :名称为 name2 生存时间为 5秒

现在使用 RENAME 命令将 name1 改名为 name2。由于 Redis 不允许存在重名的 key,因此 name2 会先被删除,然后再将 name1 改名为 name2,值得注意是,改名后的name1生存时间还是10秒!!!

过期精度

在Redis 2.4中,过期精确存在 0~1秒的时间误差。

从Redis 2.6开始,过期精确误差缩小为0~1毫秒。

Redis 2.1.3 之前

在 Redis 2.1.3 之前的版本中,修改一个带有生存时间的 key 会导致整个 key 被删除,这一行为是受当时复制(replication)层的限制而作出的,Redis 2.1.3 之后,这一限制已经被修复。

Redis 如何过期 key

Redis密钥使用两种方式过期 key

  • 被动式
  • 主动式

被动式
当客户端访问 key 时,如果 key 设置了过期时间,会检查过期时间,如果发现超时,会做超时处理(删掉key)。

当然,只依赖被动式还不够,因为有过期的 key 可能永远不会被访问,因此Redis会定期主动清理。

主动式
Redis 默认每秒执行10次以下操作

  1. 从一组相关联的带生存时间的 key中,随机抽取20个key作为样本。
  2. 删除样本中所有已过期的key。
  3. 如果样本中超过25%的key已过期,从步骤1重新开始。

过期与持久化

Key 的过期时间使用 Unix 时间戳存储(从 Redis 2.6 开始以毫秒为单位)。
当你使用 EXPIRE命令给某个 key 设置存活时间为 60 秒,redis 会把当前时间加上 60 秒作为该 key 的过期时间。这意味着即使 Redis 实例关机,key 的时间也是一直在流逝。

要想处理好 key 的过期的工作,你的计算机时间必须稳定准确!如果你将 RDB 文件在两台时间不同步的电脑间同步,可能会发生一些有趣的事情,比如所有的 key 在装载时就会过期

即使正在运行的 redis 实例也会检查计算机的时钟,例如如果你设置了一个 key 的存活时间是1000秒,在这瞬间你设置你的计算机时间为未来的1000秒,这时 key 会立即失效,而不是等1000秒之后。

AOF 相对超时

由于 AOF 持久化模式记录的是每一条 Redis 命令,因此 EXPIRE key 秒 这条命令也会被记录在 AOF 文件中。当 AOF 重建数据库时, EXPIRE key 秒 又会重置 key 的超时时间。所以对于 AOF 来说,EXPIRE 命令是相对超时。

RDB 持久化模式由于记录的是内存的快照,因此不存在该问题

EXPIREAT : 给 key 设置超时时间,精确到秒

起始版本 : 1.2.0
时间复杂度 : O(1)

EXPIREAT 具有与 EXPIRE 相同的作用,但是它没有指定表示 TTL(生存时间)的秒数,而是使用了绝对的Unix时间戳(自1970年1月1日以来的秒数)

背景

引入 EXPIREAT 是为了将AOF持久性模式的相对超时转换为绝对超时。当然,它可以直接用于指定给定密钥应在将来的给定时间到期。

语法

EXPIREAT key Unix时间戳(自1970年1月1日以来的秒数)

返回值

  • 1:设置成功
  • 0:key不存在

PEXPIRE : 给 key 设置生存时间,精确到毫秒

起始版本 : 2.6.0
时间复杂度 : O(1)

PEXPIREEXPIRE 作用和语法完全相同,只是生存时间精确到了毫秒

语法

PEXPIRE key 毫秒

返回值

  • 1:设置成功
  • 0:key不存在

PEXPIREAT : 给 key 设置超时时间,精确到毫秒

起始版本 : 2.6.0
时间复杂度 : O(1)

PEXPIREATEXPIREAT 作用和语法完全相同,只是生存时间精确到了毫秒

语法

PEXPIREAT key Unix时间戳并精确到毫秒

返回值

  • 1:设置成功
  • 0:key不存在

PERSIST : 取消 key 的超时时间,持久化 key

起始版本 : 2.2.0
时间复杂度 : O(1)

删除给 key 设置的超时时间或生存时间,将 volatile key 转变为持久化 key

语法

PERSIST key

返回值

  • 1:取消成功
  • 0:key不存在,或者 key 没有设置超时

TTL : 获取 key 剩余的生存时间,精确到秒

起始版本 : 1.0.0
时间复杂度 : O(1)

语法

TTL key

返回值

Redis 2.6或更早的版本

  • 非负数 : 剩余的生存时间,单位秒
  • -1 : key 没有关联的过期时间或 key 不存在

从Redis 2.8开始

  • 非负数 : 剩余的生存时间,单位秒
  • -1 : key 没有关联过期时间
  • -2 : key 不存在

PTTL : 获取 key 剩余的生存时间,精确到毫秒

起始版本 : 2.6.0
时间复杂度 : O(1)

语法

PTTL key

返回值

Redis 2.6或更早的版本

  • 非负数 : 剩余的生存时间,单位毫秒
  • -1 : key 没有关联的过期时间或 key 不存在

从Redis 2.8开始

  • 非负数 : 剩余的生存时间,单位毫秒
  • -1 : key 没有关联过期时间
  • -2 : key 不存在