前言
前面的章节中,我们介绍了Redis提供的一系列数据结构及其相关的命令。Redis作为一款优秀的内存数据库,因此也提供了一系列关于数据库管理方面的操作命令,因此本章主要内容就是关于Redis数据库管理方面的操作介绍。
主要内容
Redis为数据库提供了丰富的操作命令,通过这些命令,用户可以:
- 指定自己想要使用的数据库。
- 一次性获取数据库包含的所有键,迭代地获取数据库包含的所有键,或者随机地获取数据库中的某个键。
- 根据给定的键的值进行排序。
- 检查给定的一个或多个键,看他们是否存在于数据库中。
- 查看给定的键的类型。
- 对给定键进行重命名。
- 移除指定的键,或者将它从一个数据库移动到另一个数据库。
- 清空数据库包含的所有键。
- 交换给定的两个数据库。
命令速查表
下标列出了Redis数据库操作命令速查表:
命令 | 用法及参数 | 说明 |
SELECT |
| 用于切换数据库 |
KEYS |
| 获取所有与给定模式匹配的键 |
SCAN |
| 以渐进方式获取数据库键, MATCH可选项用于匹配全局匹配符 COUNT选项可以指定迭代返回键的期望数量 |
HSCAN |
| 可以以渐进的方式迭代给定的散列包含的键值对,与SCAN命令用法类似 |
SSCAN |
| 可以以渐进的方式迭代集合的元素,与SCAN命令类似 |
ZSCAN |
| 可以以渐进的方式迭代有序集合的成员和分值,与SCAN命令类似 |
RANDOMKEY |
| 随机返回一个键 |
SORT |
| 对键的值进行排序 |
EXISTS |
| 检测一个或多个键是否存在于当前使用的数据库中 |
DBSIZE |
| 获取当前使用的数据库中有多少个键值对 |
RENAME |
| 修改键的名称 |
RENAMENX |
| 只在新键名未被占用时修改名称 |
MOVE |
| 将一个键从当前数据库移动到目标数据库 |
DEL |
| 从当前正在使用的数据库中移除一个或多个指定的键,以及它们的值 |
UNLINK |
| 异步方式移除键 |
FLUSHDB |
| 清空当前正在使用的数据库 |
FLUSHALL |
| 清空所有数据库 |
SWAPDB |
| 交换数据库 |
命令详解
SELECT:切换至指定的数据库
一个Redis服务器可以包含多个数据库。在默认情况下,Redis服务器在启动的时候将会创建16个数据库:这些数据库使用号码进行标识,其中第一个数据库为 0号数据库,第二个为 1号数据库,依次类推。
SELECT index
Redis虽然不允许在同一个数据库中使用两个名称相同的键,但是不同数据库拥有不同的命名空间,所以不存在这个约束。
复杂度:
版本要求:Redis 1.0.0版本开始可用。
KEYS:获取所有匹配的键
KEYS命令接受一个全局匹配符作为参数,然后返回数据库中所有与这个匹配符相匹配的键:
KEYS pattern
Redis支持的全局匹配符如下表所示:
复杂度:
版本要求:Redis 1.0.0版本开始可用。
SCAN:以渐进方式迭代数据库键
因为KYES命令需要检查数据库包含的所有键,并一次性的将符合条件的所有键返回给客户端,所以当数据库包含的键数量比较大的时候,使用KEYS命令可能会导致服务器被阻塞。
SCAN命令是一个迭代器,它每次被调用的时候都会从数据库中获取一部分键,用户可以通过重复调用SCAN命令来迭代数据库包含的所有键:
SCAN cursor
SCAN命令的执行结果由两个元素组成:
- 第一个元素是进行下一次迭代所需要的游标,如果这个游标为0,说明已经完成了一次完整的迭代。
- 第二个元素是一个列表,这个列表包含了本次迭代取得的数据库键;如果SCAN命令在某次迭代中没有获取到任何键,那么这个元素将是一个空列表。
关于SCAN命令返回的键列表,有两点需要注意:
- SCAN命令可能会返回重复的键,用户如果不想再结果中包含重复的键,那么就需要自己在客户端进行检测和过滤;
- SCAN命令返回的键数量是不确定的,有时甚至会不返回任何键,但只要命令返回的游标不为0,迭代就没有结束。
SCAN命令的迭代保证
针对数据库的一次完整迭代以用户给定游标0调用SCAN命令开始,直到SCAN命令返回游标0结束。SCAN命令为完整迭代提供以下保证:
- 从迭代开始到结束的整个过程中,一直存在于数据库中的键总会被返回。
- 如果一个键在迭代的过程中被添加到数据库中,那么这个键是否会被返回是不确定。
- 如果一个键在迭代的过程中被移除了,那么SCAN命令在它被移除之后将不再返回这个键,但是这个键在被移除之前还是会有可能被SCAN命令返回。
- 无论数据库如何变化,迭代总是有始有终的,不会出现循环迭代或者其他无法终止迭代的情况。
游标的使用 在很多数据库中,使用游标都需要显示的申请,并且在迭代完成之后释放游标,否则就会造成内存泄漏。与此相反,SCAN命令的游标不需要申请,也不需要释放,它们不占用任何资源,每个客户端都可以使用自己的游标独立地对数据库进行迭代。 此外,用户可以随时在迭代的过程中停止迭代,或者随时开始一次新的迭代,这不会浪费任何资源,也不会引发任何问题。 |
迭代与给定匹配符相匹配的键
在默认情况下,SCAN命令会向客户端返回数据库包含的所有键,就像 KEYS那样。但是通过使用可选项 MATCH,同样可以让SCAN命令只返回与给定全局匹配符相匹配的键:
SCAN cursor [MATCH pattern]
指定返回键的期望数量
一般情况下,SCAN命令返回的键的数量是不确定的,但是我们可以使用可选项 COUNT 来指定一个期望值,以此来说明我们希望得到多少个键:
SCAN cursor [COUNT number]
特别注意:COUNT选项只是提供了一个期望值,告诉SCAN命令我们期望返回多少个键,但是每次迭代返回的数量仍然是不确定的。不过在通常情况下,设置一个较大的COUNT值将有助于获得更多的键,这一点是可以肯定的。
数据结构迭代命令
与获取数据库键的 KYES命令一样,Redis的各个数据结构也存在一些可能导致服务器阻塞的命令:
- 散列的 HKEYS 命令、HVALS命令和HGETALL命令在处理键较多的情况下,可能会导致服务器阻塞。
- 集合的 SMEMBERS命令在处理包含较多元素时,可能会导致服务器阻塞。
- 有序集合的一些范围型命令,比如 ZRANGE命令,也有可能导致服务器阻塞。
为了解决以上问题,Redis为散列、集合和有序集合也提供了一系列与SCAN命令类似的游标迭代命令,分别是:HSCAN命令、SSCAN命令、ZSCAN命令。
散列迭代命令
HSCAN命令可以以渐近的方式迭代给定散列包含的键值对:
HSCAN hash cursor [MATCH pattern] [COUNT number]
除了需要指定被迭代的散列之外,HSCAN命令的其他参数与SCAN命令的一样,作用也一样。当散列包含较多的键值对时,应该尽量使用 HSCAN命令代替 HKEYS、HVALS 和 HGETALL,以免造成服务器阻塞。
集合迭代命令
SSCAN 命令可以以渐进的方式迭代集合包含的元素:
SSCAN set cursor [MATCH pattern] [COUNT number]
SSCAN命令的参数与SCAN命令的一样,作用也一样。当集合包含较多的元素时,我们应该尽量使用SSCAN命令代替SMEMBERS命令,以免造成服务器阻塞。
有序集合迭代命令
ZSCAN命令可以以渐进的方式迭代给定的有序集合中的成员和分值:
ZSCAN sorted_set cursor [MATCH pattern] [COUNT number]
当有序集合中包含较多的成员时,应该尽量用 ZSCAN命令代替 ZRANGE命令以及其他可能会返回大量成员的范围型命令,以免造成服务器阻塞。
RANDOMKEY:随机返回一个键
RANDOMKEY命令可以从数据库中随机返回一个键:
RANDOMKEY
该命令不会移除被返回的键,它们会继续留在数据库中。
复杂度:
版本要求:Redis 1.0.0版本开始可用。
SORT:对键的值进行排序
用户可以通过执行SORT命令对列表元素、集合元素或者有序集合成员进行排序。为了让用户能够以不同的方式进行排序,Redis为SORT命令提供了非常多的可选项,如果我们以不给定任何可选项的方式执行SORT命令,那么命令将会对指定键的值按数字值进行排序:
SORT key
在默认情况下,SORT命令将按照从小到大的顺序返回排序后的各个值。
指定排序方式
默认情况下,SORT命令会按照升序的方式进行排序。通过使用可选项 ASC 或者 DESC,可以来指定排序的方式:
SORT key [ASC | DESC]
ASC表示升序也是默认的方式,DESC表示降序。
对字符串值进行排序
SORT命令默认情况下进行的都是数字值的排序,如果我们尝试直接去对字符串进行排序,将会引发错误:
127.0.0.1:6379> SORT fruits
(error) ERR One or more scores can't be converted into double
如果要对字符串进行排序,那么需要使用可选项 ALPHA 来实现:
SORT key [ALPHA]
只获取部分排序结果
默认情况下,SORT命令将返回排序后的全部元素,如果只想获取部分排序结果,那么可以使用可选项 LIMIT:
SORT key fruits [LIMIT offset count]
其中 offset参数用于指定返回结果之前需要跳过的元素数量,而count参数则用于指定需要获取的元素数量。
获取外部键的值作为结果
在默认情况下,SORT命令将返回被排序后的元素作为结果,但如果用户想要获取其他值作为排序结果,可以使用可选项 GET 来实现:
SORT key [[GET pattern] [GET pattern] ... ]
一个SORT命令可以使用任意多个GET pattern选项,其中pattern参数的值可以是:
- 包含 * 符号的字符串;
- 包含 * 符号和 **->**符号的字符串;
- 一个单独的 # 符号。
获取字符串键的值
当pattern参数的值是一个包含 * 符号的字符串时,SORT命令将把被排序的元素与 * 符号进行替换,构建出一个键名,然后使用 GET命令去获取该键的值:
字符串键 | 值 |
“apple-price” | 8.5 |
“banana-price” | 4.5 |
cherry-price" | 7 |
上述表格是用来表示水果价格的字符串类型键值对,下面用SORT命令对水果集合进行排序,然后根据排序后的结果获取对应水果的价格:
127.0.0.1:6379> SORT fruits ALPHA GET *-price
1) "8.5"
2) "4.5"
3) "7"
这个SORT命令的执行过程可分为以下三个步骤:
1)对fruits集合的各个元素进行排序,得出一个由 “apple”、“banana”、"cherry"组成的有序元素列表。
2)将排序后的各个元素与 *-price模式进行匹配和替换,得出键名:“apple-price”、“banana-price”、“cherry-price”
3)使用GET命令获取上述步骤得到的键名对应的值,并依次返回这些值。
获取散列中的键值
当pattern参数的值是一个包含 * 符号 和 -> 符号的字符串时,SORT命令将使用 -> 左边的字符串为散列名,-> 右边的字符串为字段名,调用 HGET命令,从散列中获取指定字段的值,此外,用户传入的散列名还需要包含 * 符号,这个 * 符号将被替换成被排序的元素。
散列名 | 散列中的inventory字段的值 |
“apple-info” | “1000” |
“banana-info” | “300” |
“cherry-info” | “50” |
127.0.0.1:6379> SORT fruits ALPHA GET *-info->inventory
1) "1000"
2) "300"
3) "50"
获取被排序元素本身
当pattern参数的值是一个 # 符号时,SORT命令将返回被排序的元素本身。因为SORT key命令和**SORT key GET #**命令返回的结果完全相同,所以单独使用没有实际作用。
使用外部键的值作为排序权重
在默认情况下,SORT命令将使用被排序元素本身作为排序权重,但在有需要的情况下,可以使用可选项 BY 指定其他键的值作为排序的权重:
SORT key [BY pattern]
pattern的值与 可选项 GET的一样。
保存排序结果
在默认情况下,SORT命令会将排序结果直接返回给客户端,但是如果有需要,也可以将排序结果保存到指定的键中:
SORT key [STORE destination]
如果用户给定的destination键已经存在,那么SORT命令会先移除该键,然后再存储排序的结果。
平均复杂度:,其中为被排序元素的数量,而为命令返回的元素的数量。
版本要求:Redis 1.0.0版本开始可用。
EXISTS:检查给定的键是否存在
用户可以通过EXISTS命令检查给定的一个或多个键是否存在于当前使用的数据库中:
EXISTS key [key ... ]
EXISTS命令将返回存在的给定键数量作为返回值。通过将多个键传递给EXISTS,可以判断出给定的键中,有多少个存在。
EXISTS命令从Redis 3.0.3版本开始接受多个键作为输入,在此前的版本中,只能接受一个键作为输入。
DBSIZE:获取数据库包含的键值对数量
使用DBSIZE命令可以获取当前使用的数据库中有多少个键值对:
DBSIZE
TYPE:查看键的类型
TYPE命令允许我们查看给定键的类型:
TYPE key
下标列出了TYPE命令在面对不同类型的键时返回的各项结果:
键类型 | TYPE命令返回值 |
字符串键 |
|
散列键 |
|
列表键 |
|
集合键 |
|
有序集合键 |
|
HyperLogLog |
|
位图 |
|
地理位置 |
|
流 |
|
- 因为HyperLogLog和位图这两种键在底层都是通过字符串键来实现的,所以TYPE命令对于这两种键将返回string作为结果。
- 与HyperLogLog和位图的情况类似,因为地理位置键使用了有序集合键作为底层实现,所以返回 zset作为结果。
复杂度:
版本要求:从Redis 1.0.0版本开始可用。
RENAME、RENAMENX:修改键名
Redis提供了RENAME命令来修改键的名称:
RENAME origin new
如果用户指定的新建名已经被占用,那么RENAME命令会先移除占用了新键名的那个键,然后再执行改名操作。
除了RENAME之外,还提供了RENAMENX命令,该命令也可以修改键名,但是它只会在新键名未被占用的情况下进行改名操作:
RENAMENX origin new
RENAMENX命令在改名成功时返回1,失败时返回0
MOVE:将给定的键移动到另一个数据库
用户可以使用MOVE命令,将一个键从当前数据库移动到目标数据库:
MOVE key db
当移动成功时返回1,失败返回0 ,当目标数据库存在于给定键名相同的键时,MOVE命令将放弃移动操作。
DEL:删除指定的键
使用DEL命令可以从当前正在使用的数据库中移除指定的一个或多个键,以及这些键关联的值:
DEL key [key ... ]
UNLINK:以异步方式移除指定的键
DEL命令实际上隐含着一个性能问题:因为DEL命令会以同步的方式执行移除操作,所以如果待移除的键非常庞大或者数量较多,那么服务器在执行移除操作的过程中可能会被阻塞。
为了解决这个问题,Redis从4.0版本开始新增了一个UNLINK命令:
UNLINK key [key ... ]
UNLINK命令与DEL命令一样,都可以移除指定的键,但是它是异步的方式去移除键:当用户调用UNLINK命令时,它只会在数据库中移除对该键的引用(Reference),而对键的实际移除操作则会交给后台线程执行,因此不会造成服务器阻塞。
FLUSHDB:清空当前数据库
使用FLUSHDB命令可以清空当前正在使用的数据库:
FLUSHDB [async]
其中可选项 async 用于指定FLUSHDB是否开启异步方式执行,默认情况下,FLUSHDB命令是以同步的方式执行的,这与 DEL命令一样。
FLUSHALL:清空所有数据库
使用FLUSHALL命令可以清空所有数据库:
FLUSHALL [async]
其中可选项 async 用于指定FLUSHALL是否开启异步方式执行,默认情况下,FLUSHALL命令是以同步的方式执行的,这与 DEL命令一样。
SWAPDB:交换数据库
SWAPDB命令接受两个数据库号码作为输入,然后对指定的两个数据库进行互换,最后返回OK:
SWAPDB x y
在SWAPDB命令执行成功后,原本存储在数据库 x 中的键值对将出现在 y 中,而原本在y中的键值对则出现在 x中。