承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

Redis命令使用技能之Keys的相关操作

管理员 2023-07-28 08:04:07 互联网圈 0 ℃ 0 评论 19482字 收藏

Redis命令使用技能之Keys的相关操作

前言

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

KEYS 的速度非常快,但在一个大的数据库中使用它依然可能造成性能问题,如果你需要从一个数据集中查找特定的 key ,你最好或者用 Redis 的集合结构(set)来代替。

DEL

最早可用版本1.0.0

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

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

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,因此,该命令是向后兼容的。

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

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会直接被删除。

127.0.0.1:6379> EXPIRE key1 ⑴
(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
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的参数要被设置为空字符串。

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
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
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不存在,则返回⑵;如果key是永久的,则返回⑴。

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,都会返回⑴。从2.8版本开始,如果key不存在,则返回⑵,如果key为永久key,则返回⑴。

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⑴个键值对。

List

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

Set

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

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的相关操作

https://www.wanzijz.com/view/67722.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信