keys和scan
KEYS pattern
查找所有符合给定模式pattern的key。
- keys * 匹配数据库中所有的key。
- keys h?llo 匹配hello、hfllo、hkllo等。
- keys h*llo 匹配hllo、heeello、hddffllo等。
- keys h[ae]llo 匹配hello、hallo。
keys的速度非常快,但是一个大的数据里中使用它仍然可能造成性能问题。
SCAN cursor [MATCH pattern] [COUNT count]
SCAN命令及其相关的SSCAN命令、HSCAN命令和ZSCAN命令都用于增量地迭代一个元素集合:
- SCAN命令用于迭代当前数据库中的数据库键。
- SSCAN命令用于迭代集合键中的元素。
- HSCAN命令用于迭代哈希键中的键值对。
- ZSCAN命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
以上列出的四个命令都支持增量式迭代,它们每次执行都只会返回少量元素,所以这些命令可以用于生产环境,而不会像KEYS命令、SMEMBERS命令带来的问题----当KEYS命令被用于处理一个大的数据库时,又或者SMEMBERS命令被用于处理一个大的集合键时,它们可能会阻塞服务器达数秒之久,所以在生产环境,要禁用调类似命令。
不过,增量式迭代命令也不是没有缺点:举个例子,使用SMEMBERS命令可以返回集合键当前包含的所有元素,但是对于SCAN这类增量式迭代命令来说,因为在对键进行增量式迭代的过程中,键可能会被修改,所以增量式迭代命令只能对被返回的元素提供有限的保证。
因为SCAN、SSCAN、HSCAN和ZSCAN四个命令的工作方式非常相似,所以这个文档会一并介绍这四个命令,但要记住:
- SCAN命令、HSCAN命令和ZSCAN命令的第一个参数总是一个数据库键。
- 而SCAN命令则不需要在第一个参数提供任何数据库键-----因为它迭代的是当前数据库的所有键。
SCAN命令的基本用法
SCAN命令是一个基于游标的迭代器:SCAN命令每次被调用后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为SCAN命令的游标参数,以此来延续之前的迭代过程。
当SCAN命令的游标参数被设置为0时,服务器将开始一次新的迭代,而当服务器向用户返回值为0的游标时,表示迭代结束,注意服务器返回的游标并不总是递增的。
最简单的SCAN命令执行示例:
127.0.0.1:6380> scan 0
1) "22"
2) 1) "key18"
2) "key6"
3) "key14"
4) "key3"
5) "key13"
6) "key15"
7) "EUA.DEPTPUSHTYPE.0"
8) "key"
9) "key4"
10) "EUA.NONEEDLOGIN.0"
127.0.0.1:6380> scan 22
1) "15"
2) 1) "key7"
2) "key16"
3) "key8"
4) "key1"
5) "key12"
6) "key11"
7) "key17"
8) "key9"
9) "key19"
10) "key5"
11) "key2"
127.0.0.1:6380> scan 15
1) "0"
2) (empty list or set)
127.0.0.1:6380>
SCAN命令的保证
SCAN命令,以及其他增量式迭代命令,在进行完整遍历的情况下可以为用户带来以下保证:
从完整遍历开始直到完整遍历结束期间,一直存在于数据集中的所有元素都会被完整遍历返回
因为增量式迭代命令仅仅使用游标来记录迭代状态,所以这些命令有以下缺点:
- 同一个元素可能会被返回多次。处理重复元素的工作交由应用程序负责,比如,可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上;
- 如果一个元素在迭代执行过程中被添加进数据集或者从数据集中删除,那么这个元素可能会被遍历到也可能不会被遍历到,这是未定义的。
SCAN命令每次执行返回的元素数量
增量式迭代命令并不保证每次执行都返回某个给定数量的元素。
增量式命令甚至可能会返回0个元素,但只要命令返回的游标不是0,应用程序就不应该将迭代视作结束。
不过命令返回的元素数量总是符合一定规则的,在实际中:
- 对于一个大数据集来说,增量式迭代命令每次最多可能会返回数十个元素;
- 而对于一个足够小的数据集来说,如果这个数据集的底层表示为编码数据结构(encoded data structure,适用于小集合键、小哈希键、小有序集合键),那么增量式迭代命令将在一次调用中返回数据集中的所有元素。
最后,用户可以通过增量式迭代命令提供的COUNT选项来指定每次迭代返回元素的最大值。
COUNT选项
虽然增量式迭代命令不保证每次迭代所返回的元素数量,但是可以利用COUNT选项,对命令的行为进行一定程度上的调整。
基本上,COUNT选项的作用就是让用户告知迭代命令,在每次迭代中应该从数据集中返回多少个元素。
虽然COUNT选项只是对增量式迭代命令的一种提示,但是大多数情况下,这种提示是有效的。
- COUNT参数的默认值是10.
- 在迭代一个足够大的,由哈希表实现的数据库、集合键、哈希键、有序集合键时,如果用户没有使用MATCH选项,那么命令返回的元素数量通常和COUNT选项指定的一样,或者比COUNT选项指定的数量稍多一些。
- 在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者小有序集合)时,增量式迭代命令通常会无视COUNT选项指定的值,在一次迭代就将数据集中包含的所有元素都返回给用户
并非每次迭代都要使用相同的COUNT值
用户可以在每次迭代中按自己的需要随意改变COUNT值,只要记得将上次迭代的游标用到下次迭代里面就可以了。
MATCH选项
和KEYS命令一样,增量式迭代命令也可以通过提供一个glob风格的模式参数,让命令只返回和给定模式匹配的元素,这一点可以通过在执行增量式迭代命令时,通过给定MATCH <pattern>参数来实现。
注意:对元素的模式匹配工作是在命令从数据集中取出元素之后,向客户端返回元素之前这段时间内进行的,所以如果迭代的数据集中只有少量元素和模式匹配,那么迭代命令或许会在多次执行中都不会返回任何元素。
并发执行多个迭代
在同一时间,可以有任意多个客户端对同一数据集进行迭代,客户端每次执行迭代都需要传入一个游标,并在执行迭代之后获得一个新的游标,而这个游标就包含了迭代的所有状态,因此,服务器无须为迭代记录任何状态。
中途停止迭代
因为迭代的所有状态都保存在游标里面,而服务器无须为迭代保存任何状态,所以客户端可以在中途停止一个迭代,而无须对服务器进行任何通知。
即使有任意数量的迭代在中途停止,也不会产生任何问题。
使用错误的游标进行增量式迭代
使用错误的游标来执行增量式迭代,并不会造成服务器崩溃,但可能会让命令产生未定义的行为。
未定义的行为指的是,增量式命令对返回值所做的保证可能会不再为真。
只有两种游标时合法的:
- 在开始一个新的迭代时,游标必须为0;
- 增量式迭代命令再执行之后,用于延续迭代过程的游标。
迭代终结的保证
增量式迭代命令所使用的算法只保证在数据集大小有界的情况下,迭代才会停止,也就是说,如果被迭代的数据集的大小不断增长的话,增量式迭代命令可能永远也无法完成一次完整的迭代。
返回值:
SCAN命令、SSCAN命令、HSCAN命令和ZSCAN命令都返回一个包含两个元素的multi-bulk回复:第一个元素是字符串表示的无符号64位整数,第二个元素是另一个multi-bulk回复,这个回复包含了本次所迭代的元素。
SCAN 命令返回的每个元素都是一个数据库键。
SSCAN命令返回的每个元素都是一个集合成员。
HSCAN 命令返回的每个元素都是一个键值对,一个键值对由一个键和一个值组成。
ZSCAN命令返回的每个元素都是一个有序集合元素,一个有序集合元素由一个成员(member)和一个分值(score)组成。