Redis的全量遍历和渐进式遍历

Redis提供了两种key遍历的方法,一种是keys,一种是scan,这里对它们进行讲解并分析。

1、全量遍历

keys pattern

在本专栏【认识redis】中,讲解的全局命令中有keys 的简单使用,实际上keys命令是支持pattern匹配的,如下:

#获取redis中所有键,使用keys * 命令
127.0.0.1:6379> keys *
 1) "user"
 2) "user.name"
 3) "list1"
 4) "c"
 5) "test"
 6) "b"
 7) "y"
 8) "a"
 9) "user.city"
10) "hk"
11) "list2"
12) "k"
13) "x"

上面的例子中使用的是*,这是为了匹配所有的key。

keys命令中的pattern参数使用的是glob风格的通配符,详细如下:

  • *代表匹配任意私服
  • ?代表匹配一个字符
  • [] 代表匹配部分字符,例如[a,c,e]代表匹配a,c,e,[1-10]代表匹配从1到10的任意数字。
  • \x 用来匹配转义字符,例如 需要用来匹配?、*等特殊字符时,需要进行转义

例子如下:

#匹配list开头的所有key
127.0.0.1:6379> keys list*
1) "list1"
2) "list2"

#匹配包含user的key
127.0.0.1:6379> keys [user]*
1) "user"
2) "user.name"
3) "user.city"

当需要遍历所有的键时,keys是一个十分有用的命令,但是考虑到Redis是单线程架构,如果Redis中包含大量的key时,执行keys命令,极有可能导致Redis阻塞,所有一般不建议在生产环境中使用该命令,如果业务确实需要对所有键进行遍历,可使用如下操作:

1、确认键的总数,如果总数比较少的话,可以使用该命令

2、如果键的数量比较多,可以使用渐进式遍历命令scan,能够有效避免阻塞。

2、渐进式遍历

Redis中提供了scan命令,有效解决了keys命令带来的阻塞问题。它执行时并不会遍历全部键,而是采用渐进式遍历的方式,不过想要真正实现keys的功能,需要执行多次scan命令才行。

Redis中存储键值对使用的是hashtable的数据结构,每次执行scan命令,可以看成是只扫描其中一部分键,知道将所有的键都遍历完才可以结束。scan命令如下:

scan cursor [match pattern] [count number]

命令参数为:

  • cursor:必须参数,游标,第一次遍历从0开始,每次遍历完都会返回当前的游标值,直到游标值为0,标识所有key都被遍历完成,遍历可以结束
  • match pattern : 和keys命令的匹配相似,都是用作键的匹配
  • count number: 表名每次匹配要遍历的键的个数,默认是10,可以适当调大。

示例如下:

# 第一次执行scan 0
127.0.0.1:6379> scan 0
1) "11"
2)  1) "user"
    2) "a"
    3) "test"
    4) "user.name"
    5) "hk"
    6) "y"
    7) "user.city"
    8) "b"
    9) "list1"
   10) "c"
   
# 使用新的cursor = '11',执行scan 11
127.0.0.1:6379> scan 11
1) "0"
2) 1) "list2"
   2) "k"
   3) "x"

运行命令和结果解释:

1、第一次执行scan 0 ,返回结果包括两部分,第一部分 11 就是下次执行scan命令需要的cursor参数,第二部分是返回的10个键。

2、第二次执行scan 11 ,得到的结果是 “0”,说明所有的键都已经被遍历过了。

除了scan外,Redis中还提供了针对哈希、集合、有序集合等类型的扫描遍历的命令,解决hgetall、smembers、zrange可能产生的阻塞的问题,对应的命令分别是:hscan、sscan、zscan,它们的用法和scan相似。

使用scan命令的注意事项:

scan命令能有效的解决keys命令带来的阻塞问题,但是却带来新的问题。

在scan过程中,如果键发生了变化(增、删、改),那么有可能会出现新增的键没有遍历到或者遍历出了重复键的情况。这是在开发过程中需要注意到的地方。

你可能感兴趣的:(Redis技术学习及开发运维,redis,nosql数据库,后端)