一、总结

Scan命令又细分为:scan命令,Sscan命令、Hscan命令、Zscan命令。

  • scan命令用于迭代字符串中的元素。
  • Sscan命令用于迭代集合键中的元素。
  • Hscan命令用于迭代哈希键中的键值对。
  • Zscan命令用于迭代有序集合中的元素(包括元素成员和元素分值)。

二、scan的由来

Redis中的Keys命令和Smembers命令类似于数据库中的全表扫描,其中,Smembers命令返回集合中的所有的成员,与数据库中的全表扫描无异。由于Redis是单线程,而Keys命令和Smembers命令会造成Redis线程的堵塞,在生产环境需要十分慎重的使用。

为了避免Redis线程的堵塞出现了查询迭代命令,也就是Scan命令,其用于迭代当前数据库中的缓存数据。Scan 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为Scan命令的游标参数, 以此来延续之前的迭代过程。

Scan命令返回一个包含两个元素的数组,
第一个元素:是用于进行下一次迭代的新游标(如果新游标返回 0 表示迭代已结束) 
第二个元素:则是一个数组, 这个数组中包含了所有被迭代的元素。

在同一时间,可以有任意多个客户端对同一数据集进行迭代,客户端每次执行迭代都需要传入一个游标,并在迭代执行之后获得一个新的游标,而这个游标就包含了迭代的所有状态,因此,服务器无须为迭代记录任何状态。因为迭代的所有状态都保存在游标里面,而服务器无须为迭代保存任何状态,所以客户端可以在中途停止一个迭代,而无须对服务器进行任何通知。即使有任意数量的迭代在中途停止,也不会产生任何问题。

例如:

以下是一个SCAN命令的迭代过程示例:

127.0.0.1:6379> scan 0 MATCH ops-coffee-*

1)"38"

2) "ops-coffee-25"

    "ops-coffee-19"

    "ops-coffee-29"

    "ops-coffee-10"

    "ops-coffee-23"

    "ops-coffee-5"

    "ops-coffee-14"

    "ops-coffee-16"

    "ops-coffee-11"

    "ops-coffee-15"

    "ops-coffee-7"

    "ops-coffee-1"

127.0.0.1:6379> scan 38 MATCH ops-coffee-* COUNT 1000

1) "0"

2) "ops-coffee-13"

    "ops-coffee-9"

    "ops-coffee-21"

    "ops-coffee-6"

    "ops-coffee-30"

    "ops-coffee-20"

    "ops-coffee-2"

    "ops-coffee-12"

    "ops-coffee-28"

    "ops-coffee-3"

    "ops-coffee-26"

    "ops-coffee-4"

    "ops-coffee-31"

    "ops-coffee-8"

    "ops-coffee-22"

    "ops-coffee-27"

    "ops-coffee-18"

    "ops-coffee-24"

    "ops-coffee-17"


参考自:https://www.jianshu.com/p/e325015ad5fa

上面这个例子的意思是扫描所有前缀为“ops-coffee-”的key

  • 第一次迭代:使用0作为游标,表示开始一次新的迭代,同时使用了MATCH匹配前缀为ops-coffee-的key,返回了游标值38以及遍历到的数据。
  • 第二次迭代:使用的是第一次迭代时返回的游标,也即是命令回复第一个元素的值38,同时通过将COUNT选项的参数设置为1000,强制命令为本次迭代扫描更多元素
    在第二次调用SCAN命令时,命令返回了游标0,这表示迭代已经结束,整个数据集已经被完整遍历过了。

三、扩展

1. linux shell命令

KEYS命令的时间复杂度为O(n),而SCAN命令会将遍历操作分解成m次时间复杂度为O(1)的操作来执行,从而解决使用keys命令遍历大量数据而导致服务器阻塞的情况,使用下边的指令可以达到优雅删除的目的:

redis-cli --scan --pattern "ops-coffee-*" | xargs -L 2000 redis-cli del

其中xargs -L指令表示xargs一次读取的行数,也就是每次删除的key数量,一次读取太多xargs会报错

2.  sscan 

类似的SCAN命令,对于Redis不同的数据类型还有另外几个SSCAN、HSCAN和ZSCAN,使用方法类似:

sscan ops-coffee 0 MATCH v1*

1) "7"
2) "v15"
    "v13"
    "v12"
    "v10"
    "v14"
    "v1"

与SCAN命令不同的是这几个命令需要多加一个key的参数,例如本例中的ops-coffee


转载自: 

Redis迭代查询详解:Scan命令、Sscan命令、Hscan命令、Zscan命令 - MyBatis中文官网

redis scan 优雅的批量删除 - 简书

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐