https://jackeyzhe.github.io/2018/09/22/Redis%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3%EF%BC%9AKeys/

介绍完Redis连接相关命令后,再来介绍一下与Key相关的命令,Redis作为一个key-value数据库,对Key进行操作是无法避免的。

DEL

最早可用版本1.0.0

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

1
2
3
4
5
6
127.0.0.1:6379> SET key1 "jackey"
OK
127.0.0.1:6379> SET key2 "zhe"
OK
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

1
2
3
4
5
6
127.0.0.1:6379> SET key1 "jackey"
OK
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,因此,该命令是向后兼容的。

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

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> SET key1 "jackey"
OK
127.0.0.1:6379> SET key2 "zhe"
OK
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会直接被删除。

1
2
3
4
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次下面的操作:

  1. 随机查看20个设置过存活时间的key(从设置存活时间的set中取)
  2. 删除所有过期的key
  3. 如果过期的key超过25%,那么会从第一步开始再执行一次

EXPIREAT

最早可用版本1.2.0

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

1
2
3
4
5
6
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,特殊符号使用\隔开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
127.0.0.1:6379> MSET key1hello jackey key2hello zhe age 3
OK
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的参数要被设置为空字符串。

1
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,那么这个命令什么也不做。

1
2
3
4
5
6
7
8
9
10
11
12
13
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
OK
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
1
2
3
4
5
6
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用于测试。

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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中数据类型。

UNLINK

最早可用版本4.0.0

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

WAIT

最早可用版本3.0.0

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

[转帖]Redis命令详解:Keys的更多相关文章

  1. [转帖]xargs命令详解,xargs与管道的区别

    xargs命令详解,xargs与管道的区别 https://www.cnblogs.com/wangqiguo/p/6464234.html 之前一直说要学习一下 xargs 到现在为止也没学习.. ...

  2. [转帖]dd命令详解

    dd命令详解 https://czmmiao.iteye.com/blog/1748748 之前一直对linux的命令很恐惧 现在发现 其实不是那么复杂 要仔细学习就可以了 比如 dd = disk ...

  3. [转帖]pidstat 命令详解

    pidstat 命令详解 https://www.jianshu.com/p/3991c0dba094 pidstat -r -u -d -p 各种参数非常好用. pidstat 概述 pidstat ...

  4. [转帖]ps 命令详解

    ps 命令详解 https://www.jianshu.com/p/cba22cce2f97 ps 概述 Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那 ...

  5. [转帖]iostat 命令详解

    iostat 命令详解 https://www.jianshu.com/p/5fed8be1b6e8 概述 iostat 主要用于输出磁盘IO 和 CPU的统计信息. iostat属于sysstat软 ...

  6. redis命令详解

      redis中添加key value元素:set key value;       获取元素:get key ;   redis中添加集合:lpush key value1 value2 value ...

  7. NoSQL之Redis高级实用命令详解--安全和主从复制

    Android IOS JavaScript HTML5 CSS jQuery Python PHP NodeJS Java Spring MySQL MongoDB Redis NOSQL Vim ...

  8. Python操作redis系列以 哈希(Hash)命令详解(四)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. Hset 命令用于 ...

  9. [转帖]Linux的wget命令详解

    Linux的wget命令详解 来源不明 找到的也是转帖的 https://www.cnblogs.com/cindy-cindy/p/6847502.html Linux wget是一个下载文件的工具 ...

  10. 【转帖】Linux定时任务Crontab命令详解

    Linux定时任务Crontab命令详解 https://www.cnblogs.com/intval/p/5763929.html 知道有crontab 以及 at 命令 改天仔细学习一下 讲sys ...

随机推荐

  1. 华为云“网红”语言Python课程来啦!

    摘要:来华为云社区学Python,瓜分40万码豆还有HUAWEI GT手表拿! 现代职场大量重复性的工作.日报周报月报无穷无尽.不计其数的数据提取.琐碎繁杂的事物让工作效率极低. 而Python的出现 ...

  2. 13个VSCode使用技巧,开启高效的开发模式

    摘要:VsCode是一款开源的编辑器,拥有强大的功能,.由于拥有各种各样的插件,这就使得VsCode可以做到的事情更多了.在使用的过程中,也是有很多技巧的,掌握一些技巧对于后期写代码也会轻松很多. 本 ...

  3. storybook 编写stories的story基础语法

    编写 stories story 用于展示组件某个状态,每个组件可以包含任意多个 story,用来测试组件的各种场景.根据默认配置,只需要在组件的文件夹中,以 **.component.stories ...

  4. 深度克隆从C#/C/Java漫谈到JavaScript真复制

    如果只想看js,直接从JavaScript标题开始. 在C#里面,深度clone有System.ICloneable.创建现有实例相同的值创建类的新实例 克隆原理 值类型变量与引用类型变量 如果我们有 ...

  5. ​iOS上架审核宝典:如何避免被拒一次提交成功

    Xcode 摘要:本文整理了iOS上架需要注意的事项,以帮助从事iOS开发和App运营的朋友们避免审核被拒的困扰.通过遵循这些指南,我们可以在一次提交中成功地将应用上架,并节省宝贵的时间和精力. 引言 ...

  6. 如何在Windows上将iOS应用上传到App Store

      Application Uploader iOS App上架工具是一款非常好用的针对iOS苹果应用程序软件开发的实用编程工具,它的主要作用是帮助用户进行快速的程序应用设计和程序应用调试,节省用户进 ...

  7. Filebeat的安装和使用(Windows)

    Filebeat是什么 1.Filebeat是什么?Filebeat是用于转发和集中日志数据的轻量级传送工具. Filebeat监视用户指定的日志文件或位置,收集日志事件,并将日志数据转发到Elast ...

  8. AtCoder Beginner Contest 216 个人题解

    比赛链接:Here AB水题, C - Many Balls 题意: 现在有一个数初始为 \(0(x)\) 以及两种操作 操作 \(A:\) \(x + 1\) 操作 \(B: 2\times x\) ...

  9. Codeforces Round #669 (Div. 2) A、B题题解

    Problem A - Ahahahahahahahaha https://codeforces.com/contest/1407/problem/A 题意: 给定一个偶数数组(元素值 0,1),在删 ...

  10. 【每日一题】33. 简单瞎搞题 (滚动数组 + bitset 优化DP)

    补题链接:Here 这个问题的难点在于如何统计出所有和可能出现的情况,并且不能重复. 很容易想到用桶去存储每一个数,即某个和能够组合出来则为1,否则为0 不妨令 \(dp[i][j]\) 表示为第 \ ...