如何在Redis命令中使用Keys

26次阅读
没有评论

共计 8483 个字符,预计需要花费 22 分钟才能阅读完成。

自动写代码机器人,免费开通

这篇文章给大家介绍如何在 Redis 命令中使用 Keys,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

DEL

删除指定的键值对,如果指定的 key 不存在,则忽略。DEL 命令的时间复杂度是 O(N),对于除字符串外的其他数据类型,命令的时间复杂度为 O(M),M 是值的元素的个数。所以,在生产环境尽量避免一次性删除过多复杂数据类型的操作。

127.0.0.1:6379  SET key1  jackey 
127.0.0.1:6379  SET key2  zhe 
127.0.0.1:6379  DEL key1 key2 key3
(integer) 2

DUMP

最早可用版本 2.6.0

使用一种 Redis 的格式序列化指定键存储的值。可用使用 RESTORE 命令将这个值反序列化。

这种序列化格式有以下 3 个特点:

它包含有 64 位的校验和,用于错误检查,RESTORE 命令在反序列化之前会先检查校验和

值的编码格式和 RDB 文件的编码格式相同

RDB 的版本会被序列化到值中,因此,不同版本的 Redis 可能会因为不兼容 RDB 版本而拒绝反序列化

序列化的值不包含过期时间的相关信息,可以使用 PTTL 命令获取当前值的存活时间。如果值不存在则会返回 nil

127.0.0.1:6379  SET key1  jackey 
127.0.0.1:6379  DUMP key1
 \x00\x06jackey\b\x00\xec\x89 G X\xfc: 
127.0.0.1:6379  DUMP not-exist-key
(nil)

DUMP 时间复杂度分为两部分:访问 key 值的时间复杂度为 O(1),而序列化值的时间复杂度为 O(N*M),N 是组成值的元素的数量,M 是元素的平均大小。如果序列化比较短的字符串,则该命令的时间复杂度可以看做 O(1)。

EXISTS

最早可用版本 1.0.0

用于判断 key 是否存在。3.0.3 版本以后支持多参数,即可以一次性判断多个 key,返回值是存在的 key 的数量。对于判断单个 key 是否存在,会返回 1 或者 0,因此,该命令是向后兼容的。

需要注意的是:如果参数中有重复的存在命令,则返回结果不会去重。

127.0.0.1:6379  SET key1  jackey 
127.0.0.1:6379  SET key2  zhe 
127.0.0.1:6379  EXISTS key1
(integer) 1
127.0.0.1:6379  EXISTS not-exist-key
(integer) 0
127.0.0.1:6379  EXISTS key1 key2 not-exist-key
(integer) 2
127.0.0.1:6379  EXISTS key1 key1 key1
(integer) 3

EXPIRE

最早可用版本 1.0.0

为指定的 key 设置存活时间。存活时间会被 DEL,SET,GETSET 和所有的 STORE 命令删除或者覆盖。如果我们只修改 key 的值而不修改存活时间或者保存到一个新的 key 中,则原来的 key 的存活时间保持不变。如果使用 RENAME 对一个 key 重命名,那么原有 key 的存活时间会赋给新的 key。

如果想要清除存活时间,使指定的 key 成为一个永久的 key,则可以使用 PERSIST 命令,我们稍后会详细介绍这个命令。

如果使用 EXPIRE/PEXPIRE 为某个 key 设置的存活时间为非正数,或者使用 EXPIREAT/PEXPIREAT 设置了一个过去的时间,则这个 key 会直接被删除。

127.0.0.1:6379  EXPIRE key1 -1
(integer) 1
127.0.0.1:6379  EXISTS key1
(integer) 0

对一个已经有存活时间的 key 再次使用 EXPIRE 设置存活时间,则将 key 的存活时间更新,在许多应用中我们都会用到这一点。

注意:在 Redis 的 2.1.3 版本之前,如果修改一个带有存活时间的 key 的值,则会删除整个 key。

关于时间精度,Redis2.4 版本中,一个 key 过期的一秒内仍可以访问,而到了 2.6 版本,这一时间已经被精确到了 1 毫秒。因为从 2.6 版本开始,存活时间保存的是绝对时间(Unix 的时间戳),而这就意味着,你的计算机的时间需要保证可靠,如果你将 RDB 文件放到另一台机器上加载,当这两台机器的时间差距较大时,你就会发现可能有些 key 被删除了或者有些 key 的存活时间被延长了。

下面我们在来讨论一下 Redis 究竟是如何使 key 过期的,Redis 的过期策略有两种:一种是被动的,一种是主动的。

被动过期就是当客户端访问某个 key,服务端会去检查这个 key 的存活时间,判断是否过期。当然,这种过期策略存在一定的问题,如果某个 key 一直都不访问,就不会被发现它过期了,那么它将永远“苟活”在内存中。所以 Redis 会定期随机的查看被设置过存活时间的 key,看它们是否过期,如果过期了,就会及时清理掉。Redis 每秒会做 10 次下面的操作:

随机查看 20 个设置过存活时间的 key(从设置存活时间的 set 中取)

删除所有过期的 key

如果过期的 key 超过 25%,那么会从第一步开始再执行一次

EXPIREAT

最早可用版本 1.2.0

此命令和 EXPIRE 的作用相同,不同之处是它的参数需要传 Unix 时间戳(即从 1970 年 1 月 1 日起的毫秒数)。

127.0.0.1:6379  GET key2
 zhe 
127.0.0.1:6379  EXPIREAT key2 1537733374
(integer) 1
127.0.0.1:6379  TTL key2
(integer) 12960

KEYS

最早可用版本 1.0.0

这个命令会返回匹配到的所有 key,时间复杂度为 O(N)。在官方文档中说,在入门级的笔记本电脑上,Redis 扫描 100 万条 key 只需要 40 毫秒,但是我们仍然要避免在生产环境使用这个命令。特别是千万不要使用 KEYS * 这样的命令,因为你不知道生产环境存在多少 key,这样的命令有可能使你的生产环境的 Redis 陷入很长一段时间的不可用状态。所以,请马上删除应用层代码中的 KEYS 命令或者抓紧时间更新自己的简历。

如果需要查找 key,可以使用 SCAN 命令或者 sets 命令。

虽然我们非常不建议使用 KEYS 命令,但是它的匹配策略还是要介绍一下的:

?是单个字符的通配符,* 是任意个数的通配符,[ae] 会匹配到 a 或 e,^e 表示不匹配 e,a- c 表示匹配 a 或 b 或 c,特殊符号使用 \ 隔开。

127.0.0.1:6379  MSET key1hello jackey key2hello zhe age 3
127.0.0.1:6379  KEYS key?hello
1)  key1hello 
2)  key2hello 
127.0.0.1:6379  KEYS k*
1)  key1hello 
2)  key2hello 
127.0.0.1:6379  KEYS *age*
1)  age 
127.0.0.1:6379  KEYS *
1)  age 
2)  key1hello 
3)  key2hello

MIGRATE

最早可用版本 2.6.0

这个命令用来将源实例的 key 以原子操作传输到目标实例,然后将源实例的 key 删除。相当于在源实例执行了 DUMP+DEL 操作,在目标实例执行了 RESTORE 操作。这一操作会阻塞进行传输的两个实例,在传输过程中,key 总会存在于一个实例中,除非发生超时错误。在 3.2 版本以后,MIGRATE 可以将多个 key 作为管线一次性传输。

在执行 MIGRATE 命令时,必须要设置一个超时时间,如果到了超时时间命令仍未执行完,则会抛出一个 IOERR。但返回这个错误时,两个实例的状态可能有两种:要么两个实例都存在指定的 key,要么只有源实例存在指定的 key。总之,key 是不会丢失的。

从 3.0.6 版本开始,MIGRATE 支持一次传输多个 key,为了保证不过载或者出现环形操作,MIGRATE 需要使用 KEYS 参数,而原来指定的 key 的参数要被设置为空字符串。

MIGRATE 192.168.1.34 6379   0 5000 KEYS key1 key2 key3

这里还有两个选填参数需要介绍:一个是 COPY,加上这个参数的话,传输完成后不会删除源实例中的 key。另一个是 REPLACE,这个参数的作用是替换目标实例已存在的 key。这两个参数在 3.0 版本以后才可以使用。

MOVE

最早可用版本 1.0.0

不知道大家还记不记得前文中我们提到过的 SELECT 命令,SELECT 用来切换数据库。使用 MOVE 命令就是将当前数据库的 key 移动到指定的数据库中,如果指定库中已经存在这个 key 或者当前库不存在这个 key,那么这个命令什么也不做。

127.0.0.1:6379  KEYS *
1)  age 
2)  key1hello 
3)  key2hello 
127.0.0.1:6379  MOVE age 1
(integer) 1
127.0.0.1:6379  KEYS *
1)  key1hello 
2)  key2hello 
127.0.0.1:6379  SELECT 1
127.0.0.1:6379[1]  KEYS *
1)  age

OBJECT

最早可用版本 2.2.3

OBJECT 用来查看 Redis 对象内部的相关信息。这一命令在调试时经常被使用。下面我们来介绍 OBJECT 命令的具体用法:

OBJECT REFCOUNT key:返回指定 key 的值的引用数量

OBJECT ENCODING key:返回指定 key 的内部存储使用的编码格式

OBJECT IDLETIME key:返回指定 key 的空闲时间(有多长时间没有被读写),目前最小精度为 10 秒,这一命令经常在 Redis 淘汰机制中使用(淘汰策略为 LRU 或 noeviction)

OBJECT FREQ key:返回指定 key 访问频率的对数,当淘汰策略为 LFU 时,这一命令会被用到

OBJECT HELP:返回帮助信息

对象的编码格式也有很多种:

Strings 会被编码为 raw 或 int

Lists 会被编码为 ziplist 或 linkedlist

Sets 会被编码为 intset 或 hashtable

Hashs 会被编码为 ziplist 或 hashtable

Sorted Sets 会被编码为 ziplist 或 skiplist

127.0.0.1:6379  OBJECT REFCOUNT key1hello
(integer) 1
127.0.0.1:6379  OBJECT IDLETIME key2hello
(integer) 3637
127.0.0.1:6379  OBJECT ENCODING age
 int

PERSIST

最早可用版本 2.2.0

删除指定 key 的过期时间,使之变成永久的 key。

PEXPIRE

最早可用版本 2.6.0

PEXPIRE 的作用和 EXPIRE 一样,只不过参数中的时间单位是毫秒。

PEXPIREAT

最早可用版本 2.6.0

作用和 EXPIREAT 相同,参数同样是毫秒。

PTTL

最早可用版本 2.6.0

返回指定 key 的剩余存活时间的毫秒数。2.8 以后的版本返回值有些变化,如果 key 不存在,则返回 -2;如果 key 是永久的,则返回 -1。

RANDOMKEY

最早可用版本 1.0.0

此命令用于从当前数据库返回一个随机的 key。

RENAME

最早可用版本 1.0.0

重命名一个 key。如果 key 不存在,则会返回错误。而如果新的 key 已经存在,则此命令会覆盖原来的 key(它其实是执行了一个隐式的 DEL 命令,因此如果原来的 key 存储的对象很大的话,删除操作延时会很高)。在 3.2 版本以前,如果源 key 和目标 key 相同的话,会报错。

RENAMENX

如果新的 key 不存在的话,重命名 key,如果存在的话返回 0,成功返回 1。

RESTORE

最早可用版本 2.6.0

用法:RESTORE key ttl serialized-value [REPLACE]

此命令是将一组数据反序列化,并存到 key。如果 ttl 是 0,则 key 是永久的。在 Redis3.0 版本以后,如果不使用 REPLACE 参数并且 key 已经存在,则会返回一个错误“Target key name is busy”。

SCAN

最早可用版本 2.8.0

用法:SCAN cursor MATCH pattern COUNT count

其中 cursor 为游标,MATCH 和 COUNT 为可选参数。

SCAN 命令和 SSCAN、HSCAN、ZSCAN 命令都用于增量的迭代元素集,它每次返回小部分数据,不会像 KEYS 那样阻塞 Redis。SCAN 命令是基于游标的,每次调用后,都会返回一个游标,用于下一次迭代。当游标返回 0 时,表示迭代结束。

SCAN 每次返回的数量并不固定,也有可能返回数据为空。另外,SCAN 命令和 KEYS 命令一样支持匹配。

我们在 Redis 里存入 10000 个 key 用于测试。

结果如下:

127.0.0.1:6379  scan 0 match key24* count 1000
1)  1688 
2) 1)  key2411 
 2)  key2475 
 3)  key2494 
 4)  key2406 
 5)  key2478 
127.0.0.1:6379  scan 1688 match key24* count 1000
1)  2444 
2) 1)  key2458 
 2)  key249 
 3)  key2407 
 4)  key2434 
 5)  key241 
 6)  key2497 
 7)  key2435 
 8)  key2413 
 9)  key2421 
 10)  key248 
127.0.0.1:6379  scan 2444 match key24* count 1000
1)  818 
2) 1)  key2459 
 2)  key2462 
 3)  key2409 
 4)  key2454 
 5)  key2431 
 6)  key2423 
 7)  key2476 
 8)  key2428 
 9)  key2493 
 10)  key2420 
127.0.0.1:6379  scan 818 match key24* count 1000
1)  9190 
2) 1)  key2402 
 2)  key2415 
 3)  key2429 
 4)  key2424 
 5)  key2425 
 6)  key2400 
 7)  key2472 
 8)  key2479 
 9)  key2448 
 10)  key245 
 11)  key2487 
 12)  key2430 
 13)  key2405 
127.0.0.1:6379  scan 9190 match key24* count 1000
1)  12161 
2) 1)  key2488 
 2)  key2437 
 3)  key2404 
 4)  key2440 
 5)  key2461 
 6)  key2416 
 7)  key2436 
 8)  key2403 
 9)  key2460 
 10)  key2452 
 11)  key2449 
 12)  key2482 
127.0.0.1:6379  scan 12161 match key24* count 1000
1)  11993 
2) 1)  key2483 
 2)  key2491 
 3)  key242 
 4)  key2466 
 5)  key2446 
 6)  key2465 
 7)  key243 
 8)  key2438 
 9)  key2457 
 10)  key246 
 11)  key2422 
 12)  key2418 
127.0.0.1:6379  scan 11993 match key24* count 1000
1)  7853 
2) 1)  key2498 
 2)  key2451 
 3)  key2439 
 4)  key2495 
 5)  key2408 
 6)  key2410 
127.0.0.1:6379  scan 7853 match key24* count 1000
1)  5875 
2) 1)  key2486 
 2)  key2490 
 3)  key244 
 4)  key2401 
 5)  key2463 
 6)  key2481 
 7)  key2477 
 8)  key2468 
 9)  key2433 
 10)  key2489 
 11)  key2455 
 12)  key2426 
 13)  key24 
 14)  key2450 
 15)  key2414 
 16)  key2442 
 17)  key2473 
 18)  key2467 
 19)  key2469 
 20)  key2456 
127.0.0.1:6379  scan 5875 match key24* count 1000
1)  14311 
2) 1)  key2453 
 2)  key2492 
 3)  key2480 
 4)  key2427 
 5)  key2443 
 6)  key2417 
 7)  key2432 
 8)  key240 
 9)  key2445 
 10)  key2484 
 11)  key2444 
 12)  key247 
 13)  key2485 
127.0.0.1:6379  scan 14311 match key24* count 1000
1)  16383 
2) 1)  key2441 
 2)  key2474 
 3)  key2447 
 4)  key2471 
 5)  key2470 
 6)  key2464 
 7)  key2412 
 8)  key2419 
 9)  key2499 
 10)  key2496 
127.0.0.1:6379  scan 16383 match key24* count 1000
1)  0 
2) (empty list or set)

可以看到虽然我们设置的 count 为 1000,但 Redis 每次返回的数值只有 10 个左右。

SORT

最早可用版本 1.0.0

当有 N 个元素需要排序,并且要返回 M 个元素时,SORT 命令的时间复杂度为 O(N+M*log(M))

此命令用于返回或保存 list,set 和 sorted set 的键,默认将数字或者可排序的 key 进行排序,Redis 会将其视为双精度浮点数。

如果想要对字符串按字典顺序排序,可以使用 ALPHA 参数。

如果想要按照外部字段进行排序,可以使用 BY 参数。

TOUCH

最早可用版本 3.2.1

修改某一个或多个 key 的最后访问时间,如果 key 不存在,则忽略。

TTL

最早可用版本 1.0.0

返回指定 key 的剩余存活时间,单位为秒。

在 2.6 版本及以前,如果 key 不存在或者是永久 key,都会返回 -1。从 2.8 版本开始,如果 key 不存在,则返回 -2,如果 key 为永久 key,则返回 -1。

TYPE

最早可用版本 1.0.0

返回 key 存储的值的类型。类型即为我们在 Redis 基础数据结构一文中描述的 5 中数据类型。

String

String 是最基本的,也是最常用的类型。它是二进制安全的,也就是说,我们可以将对象序列化成 json 字符串作为 value 值存入 Redis。在分配内存时,Redis 会为一个字符串分配一些冗余的空间,以避免因字符串的值改变而出现频繁的内存分配操作。当字符串长度小于 1M 时,每次扩容都会加倍现有空间,当长度大于 1M 时,每次扩容,增加 1M,Redis 字符串的最大长度是 512M。

Hash

Hash 是键值对集合,相当于 Java 中的 HashMap,实际结构也和 HashMap 一样,是数组 + 链表的结构。所不同的是扩容的方式不同,HashMap 是进行一次 rehash,而 Redis 为了不阻塞服务,会创建一个新的数组,在查询时会同时查询两个 Hash,然后在逐渐将旧的 Hash 内容转移到新的中去。一个 Hash 最大可以存储 232- 1 个键值对。

List

List 相当于 Java 中的 LinkedList,它的插入和删除操作的时间复杂度为 O(1),而查询操作的时间复杂度为 O(n)。我们可以利用 List 的 rpush、rpop、lpush 和 lpop 命令来构建队列或者栈。列表最多可以存储 232- 1 个元素。

Set

Set 是 String 类型的无序集合,并且元素唯一,相当于 Java 中的 HashSet,它的插入、删除、查询操作的时间复杂度都是 O(1)。其最大元素数也是 232- 1 个。

zset

zset 可以看做是 Java 中 SortedSet 和 HashMap 的结合,一方面它不允许元素重复,另一方面,它通过 score 为每个元素进行排序。

UNLINK

最早可用版本 4.0.0

这个命令和 DEL 类似,会删除指定的 key。所不同的是,此命令的时间复杂度为 O(1),它先将 key 从 keyspace 中删除,此时指定的 key 已经删除,但是内存没有释放。所以,这个命令会在另一个线程中做释放内存的操作。这一步的操作时间复杂度为 O(N)。

WAIT

最早可用版本 3.0.0

这个命令会阻塞客户端,直到前面所有的写操作都完成并且保存了指定数量的副本。该命令总会返回副本数量或者超时。

关于如何在 Redis 命令中使用 Keys 就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计8483字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)