redis的scan命令
- redis是单线程的,因此使用一些时间复杂度为0(N)的命令要十分谨慎,容易阻塞
- 使用keys命令查询key容易阻塞
- 没有limit
- 遍历算法,复杂度O(N)
- scan命令(SCAN cursor [MATCH pattern] [COUNT count])
- 特点
- 有limit参数,可以控制每次返回结果的最大条数
- 复杂度虽然也是0(N),但分次进行,不会阻塞线程
- 结构
- redis使用hash作为底层实现,数据+链表的结构,数组的大小为2n(n>=0)。每次扩容数组长度扩大一倍
- scan命令遍历这个一位数组,每次返回的游标值是这个数组的索引,limit表示遍历多少个数组的元素,将这些元素下挂接的符合条件的结果都返回。因为每个元素下挂接的链表大小不同,所以每次返回的结果数量也就不同
- 遍历顺序(二进制高位加1)(考虑了扩容和缩容)(游标倒置加1再倒置)
- rehash
- 扩容:原来挂接在xx下的所有元素被分配到0xx和1xx下。在上图中,当我们即将遍历10时,dict进行了rehash,这时,scan命令会从010开始遍历,而000和100(原00下挂接的元素)不会再被重复遍历
- 缩容:假设dict从3位缩容到2位,当即将遍历110时,dict发生了缩容,这时scan会遍历10。这时010下挂接的元素会被重复遍历,但010之前的元素都不会被重复遍历了。所以,缩容时还是可能会有些重复元素出现的
- 特点