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

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  1. 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. 1
  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. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  1. 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. 1
    2
    3
    4
    5
    6
  1. 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. 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
  1. 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. 详解Native Memory Tracking 追踪区域分析

    摘要:本篇将介绍NMT追踪区域的部分内存类型--Java heap.Class.Thread.Code 以及 GC. 本文分享自华为云社区<Native Memory Tracking 详解(2 ...

  2. 当你运行npm run命令时,会发生什么?

    摘要:今天我们来聊一聊运行npm run命令之后会发生什么. 本文分享自华为云社区<运行npm run命令的时候会发生什么?>,作者:gentle_zhou . 先前发了一篇"运 ...

  3. 火山引擎 LAS Spark 升级:揭秘 Bucket 优化技术

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 文章介绍了 Bucket 优化技术及其在实际业务中的应用,包括 Spark Bucket 的基本原理,重点阐述了火 ...

  4. Runnable接口的 run() 方法和start()方法

    1.start()方法来启动线程,真正实现了多线程运行.这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码:通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就 ...

  5. dom4j selectNodes 取不到值 因为XML带有命名空间 HL7

    xml 如下: <?xml version="1.0" encoding="UTF-8"?> <POOR_IN200901UV ITSVers ...

  6. C#开源免费的Blazor图表库

    前言 今天分享一款基于ApexCharts.js封装的.C#开源免费的Blazor图表库:Blazor-ApexCharts. 10款值得推荐的Blazor UI组件库 全面的ASP.NET Core ...

  7. VS Code的C/C++环境配置的傻瓜式教程(看这一篇就够了)

    html: toc: true VS Code的C/C++环境配置的傻瓜式教程(看这一篇就够了) 写在前面的话 作者在学习使用vscode写C代码的时候,根据网上很多参差不齐的教程踩了不少的坑,很多教 ...

  8. Dapper.Lite 使用教程

    以MySQL数据库为例 一. 安装 NuGet搜索Dapper.Lite并安装最新版本. NuGet搜索MySqlConnector并安装最新版本. 也可以使用MySql.Data库,但MySqlCo ...

  9. Java字节码与反射机制

    字节码(Byte Code)是Java语言跨平台特性的重要保障,也是反射机制的重要基础.通过反射机制,我们不仅能看到一个类的属性和方法,还能在一个类里调用另外一个类的方法,但前提是我们得有相关类的字节 ...

  10. 如何让 Llama2、通义千问开源大语言模型快速跑在函数计算上?

    本文是"在Serverless平台上构建AIGC应用"系列文章的第一篇文章. 前言 随着ChatGPT 以及 Stable Diffusion,Midjourney 这些新生代 A ...