redis scan命令的使用
scan命令的简介
scan相关的命令有sscan、hscan、zscan,这些命令都用于增量的迭代:
scan:用于迭代当前数据库中的数据键
sscan:用于迭代集合键中的元素
hscan:用于迭代哈希键重的键值对
zscan:用于迭代有序集合中的元素
scan相关命令与keys xx*的比较
scan相关命令都支持增量式迭代,他们每次执行都会返回少量元素,因此这些命令可以用于生产环境,不会出现像keys命令、smembers命令在处理大量数据时而产生的长达数秒的服务器阻塞。
scan命令的基本用法
SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
下面以一个例子来说明操作过程:(一个十五个key,分别是1-15)
---------------------------------------------------------------------------------------------------------------------------------------------------------
个人虚拟机测试:0>scan 0
- “3”
-
- “12”
- “5”
- “14”
- “9”
- “13”
- “4”
- “7”
- “2”
- “3”
- “6”
个人虚拟机测试:0>scan 3
- “0”
-
- “10”
- “1”
- “11”
- “15”
- “8”
从上面这个例子可以看出来,迭代会返回两个元素,第一个为下一次开始迭代的游标起始值,第二个元为数组,为十个key;返回的游标值为0的时候,代表整个数据集已经被遍历完成。那么以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历。该例子就是一个完整遍历。
scan命令的可靠性
SCAN 命令, 以及其他增量式迭代命令, 在进行完整遍历的情况下可以为用户带来以下保证: 从完整遍历开始直到完整遍历结束期间, 一直存在于数据集内的所有元素都会被完整遍历返回; 这意味着, 如果有一个元素, 它从遍历开始直到遍历结束期间都存在于被遍历的数据集当中, 那么 SCAN 命令总会在某次迭代中将这个元素返回给用户。
然而因为增量式命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点:
同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。
如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义。
SCAN 命令每次执行返回的元素数量
增量式迭代命令并不保证每次执行都返回某个给定数量的元素。
增量式命令甚至可能会返回零个元素, 但只要命令返回的游标不是 0 , 应用程序就不应该将迭代视作结束。
不过命令返回的元素数量总是符合一定规则的, 在实际中:
对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;
而对于一个足够小的数据集来说, 如果这个数据集的底层表示为编码数据结构(encoded data structure,适用于是小集合键、小哈希键和小有序集合键), 那么增量迭代命令将在一次调用中返回数据集中的所有元素。
最后, 用户可以通过增量式迭代命令提供的 COUNT 选项来指定每次迭代返回元素的最大值。
COUNT 选项
虽然增量式迭代命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT 选项, 对命令的行为进行一定程度上的调整。
基本上, COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。
虽然 COUNT 选项只是对增量式迭代命令的一种提示(hint), 但是在大多数情况下, 这种提示都是有效的。
COUNT 参数的默认值为 10 。
在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时, 如果用户没有使用 MATCH 选项, 那么命令返回的元素数量通常和 COUNT 选项指定的一样, 或者比 COUNT 选项指定的数量稍多一些。
在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、 或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者一个小有序集合)时, 增量式迭代命令通常会无视 COUNT 选项指定的值, 在第一次迭代就将数据集包含的所有元素都返回给用户。
个人虚拟机测试:0>scan 0 count 15
- “0”
-
1) "12" 2) "5" 3) "14" 4) "9" 5) "13" 6) "4" 7) "7" 8) "2" 9) "3" 10) "6" 11) "10" 12) "1" 13) "11" 14) "15" 15) "8" 注意:用户可以在每次迭代中按自己的需要随意改变 COUNT 值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。
MATCH 选项
和 KEYS 命令一样, 增量式迭代命令也可以通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH <pattern> 参数来实现。
以下是一个使用 MATCH 选项进行迭代的示例:
个人虚拟机测试:0>scan 0 match 1* count 30
- “0”
-
- “12”
- “14”
- “13”
- “10”
- “1”
- “11”
- “15”
并发执行多个迭代
在同一时间, 可以有任意多个客户端对同一数据集进行迭代, 客户端每次执行迭代都需要传入一个游标, 并在迭代执行之后获得一个新的游标, 而这个游标就包含了迭代的所有状态, 因此, 服务器无须为迭代记录任何状态。
中途停止迭代
因为迭代的所有状态都保存在游标里面, 而服务器无须为迭代保存任何状态, 所以客户端可以在中途停止一个迭代, 而无须对服务器进行任何通知。
即使有任意数量的迭代在中途停止, 也不会产生任何问题。
##使用错误的游标进行增量式迭代
使用间断的(broken)、负数、超出范围或者其他非正常的游标来执行增量式迭代并不会造成服务器崩溃, 但可能会让命令产生未定义的行为。
未定义行为指的是, 增量式命令对返回值所做的保证可能会不再为真。
只有两种游标是合法的:
在开始一个新的迭代时, 游标必须为 0 。
增量式迭代命令在执行之后返回的, 用于延续(continue)迭代过程的游标。