前言

前面的章节中,我们介绍了Redis提供的一系列数据结构及其相关的命令。Redis作为一款优秀的内存数据库,因此也提供了一系列关于数据库管理方面的操作命令,因此本章主要内容就是关于Redis数据库管理方面的操作介绍。

主要内容

Redis为数据库提供了丰富的操作命令,通过这些命令,用户可以:

  • 指定自己想要使用的数据库
  • 一次性获取数据库包含的所有键,迭代地获取数据库包含的所有键,或者随机地获取数据库中的某个键
  • 根据给定的键的值进行排序
  • 检查给定的一个或多个键,看他们是否存在于数据库中
  • 查看给定的键的类型
  • 对给定键进行重命名
  • 移除指定的键,或者将它从一个数据库移动到另一个数据库
  • 清空数据库包含的所有键
  • 交换给定的两个数据库

命令速查表

下标列出了Redis数据库操作命令速查表:

命令

用法及参数

说明

SELECT

SELECT index

用于切换数据库

KEYS

KEYS pattern

获取所有与给定模式匹配的键

SCAN

SCAN cursor [MATCH pattern] [COUNT number]

以渐进方式获取数据库键, MATCH可选项用于匹配全局匹配符

COUNT选项可以指定迭代返回键的期望数量

HSCAN

HSCAN hash cursor [MATCH pattern] [COUNT number]

可以以渐进的方式迭代给定的散列包含的键值对,与SCAN命令用法类似

SSCAN

SSCAN set cursor [MATCH pattern] [COUNT number]

可以以渐进的方式迭代集合的元素,与SCAN命令类似

ZSCAN

ZSCAN sorted_set cursor [MATCH pattern] [COUNT number]

可以以渐进的方式迭代有序集合的成员和分值,与SCAN命令类似

RANDOMKEY

RANDOMKEY

随机返回一个键

SORT

SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]

对键的值进行排序

EXISTS

EXISTS key [key ... ]

检测一个或多个键是否存在于当前使用的数据库中

DBSIZE

DBSIZE

获取当前使用的数据库中有多少个键值对

RENAME

RENAME origin new

修改键的名称

RENAMENX

RENAMENX origin new

只在新键名未被占用时修改名称

MOVE

MOVE key db

将一个键从当前数据库移动到目标数据库

DEL

DEL key [key ... ]

从当前正在使用的数据库中移除一个或多个指定的键,以及它们的值

UNLINK

UNLINK key [key ... ]

异步方式移除键

FLUSHDB

FLUSHDB [async]

清空当前正在使用的数据库

FLUSHALL

FLUSHALL [async]

清空所有数据库

SWAPDB

SWAPDB x y

交换数据库

命令详解

SELECT:切换至指定的数据库

一个Redis服务器可以包含多个数据库。在默认情况下,Redis服务器在启动的时候将会创建16个数据库:这些数据库使用号码进行标识,其中第一个数据库为 0号数据库,第二个为 1号数据库,依次类推。

SELECT index

Redis虽然不允许在同一个数据库中使用两个名称相同的键,但是不同数据库拥有不同的命名空间,所以不存在这个约束。

复杂度:redis 使用手册 redis操作手册_数据库
版本要求:Redis 1.0.0版本开始可用。

KEYS:获取所有匹配的键

KEYS命令接受一个全局匹配符作为参数,然后返回数据库中所有与这个匹配符相匹配的键:

KEYS pattern

Redis支持的全局匹配符如下表所示:

redis 使用手册 redis操作手册_数据库_02


复杂度:redis 使用手册 redis操作手册_redis_03

版本要求: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命令代替 HKEYSHVALSHGETALL,以免造成服务器阻塞。

集合迭代命令

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 使用手册 redis操作手册_数据库
版本要求: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 使用手册 redis操作手册_迭代_05,其中redis 使用手册 redis操作手册_redis_06为被排序元素的数量,而redis 使用手册 redis操作手册_redis 使用手册_07为命令返回的元素的数量。
版本要求: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命令返回值

字符串键

string

散列键

hash

列表键

list

集合键

set

有序集合键

zset

HyperLogLog

string

位图

string

地理位置

zset


stream

  • 因为HyperLogLog和位图这两种键在底层都是通过字符串键来实现的,所以TYPE命令对于这两种键将返回string作为结果。
  • HyperLogLog和位图的情况类似,因为地理位置键使用了有序集合键作为底层实现,所以返回 zset作为结果。

复杂度:redis 使用手册 redis操作手册_数据库
版本要求:从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中。