1.1.1. 09.大海捞针-scan


在平时 Redis 维护过程中,可能需要从成千上万个 key 中找到特定前缀的 key 列表来手动处理数据。Redis 给了几种方法来处理:

keys 指令

指令:keys [正则]

127.0.0.1:6379> keys *
1) "company"
2) "city"
3) "demo"

127.0.0.1:6379> keys c*
1) "company"
2) "city"

这个指令虽然方便,但是有几个缺点:

  1. 没有 limit offset 参数,一次性吐出所有满足条件的 key,如果有上万个那么结果将刷屏。
  2. keys 算法是遍历算法,时间复杂度是 O(n)。如果有上千万条 key,执行这个指令的时候服务器会卡顿。由于 Redis 是单线程程序,顺序执行所有指令,其他指令必须等 keys 指令执行完成后才可继续执行。

为了解决这个问题,Redis 又推出了 scan 指令

scan 指令

scan 指令的特点:

  1. 时间复杂度是 O(n),但是它是通过游标分步进行的,不会阻塞线程。
  2. 提供 limit 参数,可以控制返回结果的最大数量,但是 limit 只是一个 hint(提示),返回结果可多可少。
  3. 同 keys 一样,提供匹配功能。
  4. 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数。
  5. 返回的结果中可能有重复,需要客户端去重,很重要!!!。
  6. 遍历的过程中如果有数据修改,不确定是否能遍历到。
  7. 单次返回的结果为空不代表遍历结束,而是看返回的游标值是否为零。

指令:scan [cursor] match [匹配] [count]。cursor=游标

事先造 10 个 key。

127.0.0.1:6379> scan 0 match key* count 3
1) "14"
2) 1) "key6"
   2) "key8"
   3) "key20"
127.0.0.1:6379> scan 14 match key* count 3
1) "1"
2) 1) "key7"
   2) "key5"
127.0.0.1:6379> scan 1 match key* count 3
1) "11"
2) 1) "key9"
   2) "key4"
127.0.0.1:6379> scan 11 match key* count 3
1) "15"
2) 1) "key1"
   2) "key3"
127.0.0.1:6379> scan 15 match key* count 3
1) "0"
2) 1) "key2"

返回第一个结果是游标,作为第二次执行指令。可以理解为第二页的页码,当游标的值为 0 时,则代表遍历结束,也就是平时我们所说的尾页。

除了 scan,其他容器也有类似指令,如 zscan 遍历 zset 集合,hscan 遍历 hash 字典的集合,sscan 遍历 set 集合。

大 key 扫描

为了定位大 key,又想避免线上 Redis 卡顿,官方为我们带来了一个指令 --bigkeys。

redis-cli -h127.0.0.1 -p 7001 --bigkeys

如果担心这个指令会大幅提升线上 Redis 的 ops。可以加一个休眠参数

redis-cli -h127.0.0.1 -p 7001 --bigkeys -i 0.1

这个参数代表每隔 100 条就会休眠 0.1s。

结果

~ redis-cli --bigkeys -i 0.1

# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

[00.00%] Biggest string found so far 'key6' with 1 bytes
[00.00%] Biggest zset   found so far 'city' with 2 members
[00.00%] Biggest zset   found so far 'company' with 5 members

-------- summary -------

Sampled 13 keys in the keyspace!
Total key length in bytes is 56 (avg len 4.31)

Biggest string found 'key6' has 1 bytes
Biggest   zset found 'company' has 5 members

0 lists with 0 items (00.00% of keys, avg size 0.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
10 strings with 10 bytes (76.92% of keys, avg size 1.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
1 MBbloom--s with 0 ? (07.69% of keys, avg size 0.00)
2 zsets with 7 members (15.38% of keys, avg size 3.50)
Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-12-10 21:45:40

results matching ""

    No results matching ""