找不到匹配的key exchange算法_Redis模糊匹配的命令,要用scan,不要用keys

对于Redis服务器的维护,有时我们需要从成千上万的key中,找出我们指定的key,也就是模糊匹配出来的key,redis提供了一个简单粗暴的命令:keys,它可以用来列出所有满足特定正则字符串规则的 key。

14124e197ca6c2365ac9f8915d11cf01.png

但是对于这个简单粗暴的命令,要是不想被同事吊,生产环境就忘记有这个命令的存在,或者是这个命令在生产环境已经被老大给和谐了,原因想必大家也知道,这个指令没有offset、limit 参数,一次性吐出所有满足条件的key,万一实例中有上百万个key满足条件,你就傻眼了,并且其他同事开发的模块也在调用同一个Redis服务器的时候,他们想杀你的心都有了,keys算法是遍历算法,复杂度是 O(n),如果实例中有千万级以上的 key,这个指令就会导致 Redis 服务卡顿,所有读写Redis的其它的指令都会被延后甚至会超时报错,因为 Redis是单线程程序,顺序执行所有指令,其它指令必须等到当前的 keys 指令执行完了才可以继续。这里插个闲话,Redis也逃脱不了真香定理,要向多线程方向发展,Redis 6.0引入的最重大的改变就是多线程IO,对性能提升至少是一倍以上,等大家升级到6.0版本以上之后,也许keys命令的弊病就没有了,不过还没验证。

51beff846ba7b985abdb8a47d2af7c45.png

先不说多线程版本的Redis,先来说一下单线程版本的Redis是怎么解决这个遍历key的问题,redis提供了另外一个命令,就是scan:

scan命令的特点如下:

1、复杂度和keys命令一样,也是 O(n),但是它是通过游标分步进行的,不会阻塞线程

2、提供limit参数,可以控制每次返回结果的最大条数,这里是最大条数,而不是等于limit的条数,因为是匹配查询,是在limit的范围内匹配查询

3、返回的结果可能会有重复

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

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

0a152c00272971871cdc62d6d0e24e5b.png

scan的命令格式为:

SCAN cursor [MATCH pattern] [COUNT count]

其中cursor是游标位置,是整数值;pattern是遍历key的正则表达式;count是遍历元素的最大条数。

先写一个程序向redis服务器写入一万个key:

6e5fe150cca2cd913e36a2819b355960.png

然后用scan遍历符合bingmayong88的元素:

005437b6d595e3cee0051d9c8e0a63fd.png

大家都知道Java中HashMap的底层实现结构,是数组+链表的形式,在JDK1.7之后还加入了红黑树,在Redis当中,所有的key都存储在一个很大的字典中,这个字典结构就是一维数组+二维链表的结构,scan指令返回的游标就是第一维数组的位置索引,这个位置索引称为槽 (slot)。 如果不考虑字典的扩容缩容,直接按数组下标挨个遍历就行了。limit 参数就表示需要遍历的槽位数,之所以返回的结果可能多可能少,是因为不是所有的槽位上都会挂接链表,有些槽 位可能是空的,还有些槽位上挂接的链表上的元素可能会有多个。每一次遍历都会将 limit 数量的槽位上挂接的所有链表元素进行模式匹配过滤后,一次性返回给客户端。

fc7172c921ed6e4e88e9e0c15cf7f64e.png

从图中可以看出,scan 的遍历顺序非常特别。它不是从第一维数组的第 0 位一直遍历到末尾,而是采用 了高位进位加法来遍历。之所以使用这样特殊的方式进行遍历,是考虑到字典的扩容和缩容 时避免槽位的遍历重复和遗漏。关于高位进位加法,大家有兴趣的可以查阅资料了解一下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值