Redis的scan命令学习

303 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

1.scan和keys

都是遍历获取key的。
keys:
简单粗暴会返回所有匹配的key。当key过多的时候阻塞,会会造成服务器卡顿,所有后续执行redis的命令会延时或者超时报错。

scan:
1、复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程; 
2、提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hint,返回的
结果可多可少; 
3、同 keys 一样,它也提供模式匹配功能; 
4、服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数; 
5、返回的结果可能会有重复,需要客户端去重复,这点非常重要; 
6、遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的; 
7、单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零; 

2.scan命令

2.1命令

scan cursor MATCH pattern COUNT count

2.2.scan例子说明

scan 0 match key* count 2
第一次迭代使用 `0` 作为游标, 表示开始一次新的迭代。
返回的第一条数据为槽位,标识下一次开始的地方,直到返回为0标识结束。
count 2 标识的是槽位数,而不是返回的条数

image.png

2.3sand的遍历和扩容

从上面对图可以看出scan返回的槽位数据是从大到小,也就是从高位到低位。
这样做是为了扩容和缩容的时候避免槽位的遗漏和重复

image.png

首先容量是2的N次方,扩容或者缩容的时候都是2的倍数。
a 1  001   1%8=1               1%16=1
b 6  110   6%8=6               6%16=6
c 3  011   3%8=3   扩大一倍后   3%16=3
d 14 1110  14%8=6              14%16=14
e 11 1011  11%8=3              11%16=11
f 11 1011  11%8=3              11%16=11

可以看到d、e、f的槽位发生了变化

高位到低位
   00      10      01      11
000 100 010 110 001 101 011 111
遍历到01的时候扩容那么会从 001 开始遍历,前面已经遍历过的数据则不会再遍历了。

2.4redis扩容-》渐进式 rehash

2.5大key定位指令

redis-cli -a 123654 --bigkeys
redis-cli -a 123654 --bigkeys -i 0.1
上面这个指令每隔 100 条 scan 指令就会休眠 0.1s