其中m0、m1为当前哈希表大小减一,rev是二进制逆序。
看到这里,不知道在座的各位是不是也是跟我一样是下面这个表情
让我们来模拟一下问题,就清楚了。
我们假设现在在一个四个节点的哈希表中遍历,如下图,游标的遍历节点为:0 -> 2 -> 1 -> 3 :
再来模拟8节点的情况:
看到这里是不是稍微明白了,上面那段代码就是在当前的有效位数(比如四节点则有效位数2)范围内,从左到右进一位。
假设在遍历了0,返回2之后,字典进行了扩容,则接下来应该访问 2 -> 6 -> 1 -> 5 -> 3 -> 7。
小灰:咦,那4不是遗漏了吗?
4已经在第一轮遍历0的时候,把扩容后的4的数据也访问了。
所以,假设扩容前有效位为m,因为redis的哈希表扩容每次都是当前节点满了( use==size)的时候扩容为大于size的2^N,所以扩容后有效位则为m+1。
上面那段代码其实是保持低位的m位不变,高位一个为0一个为1。这样就保证了扩容后,跳过了的节点已经在之前被访问过,因为跳过的节点是被访问过的节点分出来的。
缩容同理,可以自己推一下。
看到这里,是不是觉得redis的scan游标设计的很巧妙呢?
小灰:原来如此,看来我又可以去查数据了呢!
最后附上完整的rehash过程中scan的代码:
总结
到此这篇关于redis中scan命令的基本实现方法的文章就介绍到这了,更多相关redis中scan命令实现内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!