scan与keys

如何从大量的key中年找到自己想要的特定key列表呢?常用的keys指令有几个缺点:

缺点1:没有offset、limit参数,因此会一次性吐出所有满足条件的key。

缺点2:keys算法是遍历算法,复杂度是O(n),该指令就会导致Redis服务卡顿。

为了解决该问题Redis2.8时新加入了scan指令。scan指令有如下特征:

①:复杂度虽然也是O(n),但通过游标分步进行的,不会阻塞线程;

②:提供limit参数来控制每次返回结果的最大条数;

③也提供模式匹配功能;

④服务器不需要为游标保存状态,游标的唯一状态就是scan返回给客户端的游标整数;

⑤返回的结果可能会有重复,需要客户端去重复;

⑥遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;

⑦单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;

scan 参数有三个参数:第一个是cursor整数值、第二个是 key的正则模式、第三个是遍历的limit hint。

第一次遍历时,cursor值为0,然后将返回结果中第一个整数值作为下一次遍历的cursor。一直遍历到返回的cursor值为0时结束。而limit不是限定返回结果的数量,而是限定服务器单次遍历的字典槽位数量(约等于),即便返回结果是空的,但是游标值不为零,意味着遍历还没结束。

这里重点解释一下limit所谓的槽位是什么:所有的key都存储在一个很大的字典中,跟Java的HashMap一样,是一维数组+二维链表结构,第一维数组的大小总是 2^n(n>=0),扩容一次数组大小空间加倍,也就是 n++。

scan 指令返回的游标就是第一维数组的位置索引,我们将这个位置索引称为槽 (slot)。如果不考虑字典的扩容缩容,直接按数组下标挨个遍历就行了。limit 参数就表示需要遍历的槽位数,之所以返回的结果可能多可能少,是因为不是所有的槽位上都会挂接链表,有些槽位可能是空的,还有些槽位上挂接的链表上的元素可能会有多个。每一次遍历都会将 limit 数量的槽位上挂接的所有链表元素进行模式匹配过滤后,一次性返回给客户端。

scan 指令是一系列指令,还可以对指定的容器集合进行遍历。比如zscan遍历zset集合元素,hscan遍历hash字典的元素、sscan 遍历set集合的元素。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值