[转帖]Redis Scan 原理解析与踩坑
https://www.cnblogs.com/jelly12345/p/16424080.html
1. 概述
由于 Redis 是单线程在处理用户的命令,而 Keys 命令会一次性遍历所有 Key,于是在 命令执行过程中,无法执行其他命令。这就导致如果 Redis 中的 key 比较多,那么 Keys 命令执行时间就会比较长,从而阻塞 Redis。
所以很多教程都推荐使用 Scan 命令来代替 Keys,因为 Scan 可以限制每次遍历的 key 数量。
Keys 的缺点:
1)没有limit,我们只能一次性获取所有符合条件的key,如果结果有上百万条,那么等待你的就是“无穷无尽”的字符串输出。
2)keys命令是遍历算法,时间复杂度是O(N)。如我们刚才所说,这个命令非常容易导致Redis服务卡顿。因此,我们要尽量避免在生产环境使用该命令。
相比于keys命令,Scan命令有两个比较明显的优势:
1)Scan命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程。
2)Scan命令提供了 count 参数,可以控制每次遍历的集合数。
可以理解为 Scan 是渐进式的 Keys。
Scan 命令语法如下:
SCAN cursor [MATCH pattern] [COUNT count]
- cursor - 游标。
- pattern - 匹配的模式。
- count - 指定每次遍历多少个集合。
- 可以简单理解为每次遍历多少个元素
- 根据测试,推荐 Count大小为 1W。
Scan 返回值为数组,会返回一个游标+一系列的 Key
大致用法如下:
SCAN命令是基于游标的,每次调用后,都会返回一个游标,用于下一次迭代。当游标返回0时,表示迭代结束。
第一次 Scan 时指定游标为 0,表示开启新的一轮迭代,然后 Scan 命令返回一个新的游标,作为第二次 Scan 时的游标值继续迭代,一直到 Scan 返回游标为0,表示本轮迭代结束。
通过这个就可以看出,Scan 完成一次迭代,需要和 Redis 进行多次交互。
Scan 命令注意事项:
- 返回的结果可能会有重复,需要客户端去重复,这点非常重要;
- 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
- 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;
2. Scan 踩坑
使用时遇到一个 特殊场景,跨区域远程连接 Redis 并进行模糊查询,扫描所有指定前缀的 Key。
最开始也没多想,直接就是开始 Scan,然后 Count 参数指定的是 1000。
Redis 中大概几百万 Key。
最后发现这个接口需要几十上百秒才返回。
什么原因呢?
Scan 命令中的 Count 指定一次扫描多少 Key,这里指定为 1000,几百万Key就需要几千次迭代,即和 Redis 交互几千次,然后因为是远程连接,网络延迟比较大,所以耗时特别长。
最后将 Count 参数调大后,减少了交互次数,就好多了。
Count 参数越大,Redis 阻塞时间也会越长,需要取舍。
极限一点,Count 参数和总 Key 数一致时,Scan 命令就和 Keys 效果一样了。
Count 大小和 Scan 总耗时的关系如下图:

可以发现 Count 越大,总耗时就越短,不过越后面提升就越不明显了。
所以推荐的 Count 大小为 1W 左右。
如果不考虑 Redis 的阻塞,其实 Keys 比 Scan 会快很多,毕竟一次性处理,省去了多余的交互。
3. Scan原理
Redis使用了Hash表作为底层实现,原因不外乎高效且实现简单。类似于HashMap那样数组+链表的结构。其中第一维的数组大小为2n(n>=0)。每次扩容数组长度扩大一倍。
Scan命令就是对这个一维数组进行遍历。每次返回的游标值也都是这个数组的索引。Count 参数表示遍历多少个数组的元素,将这些元素下挂接的符合条件的结果都返回。因为每个元素下挂接的链表大小不同,所以每次返回的结果数量也就不同。
[转帖]Redis Scan 原理解析与踩坑的更多相关文章
- Spring boot redis自增编号控制 踩坑
近段期间,公司 接手一个订单号生成服务,规则的话已经由项目经理他们规定好了,主要是后面的四位数代表的关于当前订单号已经执行第几个了.而这里面有一个要求就是支持分布式.为了实现这个东西,刚开始我使用了r ...
- TensorFlow保存、加载模型参数 | 原理描述及踩坑经验总结
写在前面 我之前使用的LSTM计算单元是根据其前向传播的计算公式手动实现的,这两天想要和TensorFlow自带的tf.nn.rnn_cell.BasicLSTMCell()比较一下,看看哪个训练速度 ...
- Redis中的Scan命令踩坑记
1 原本以为自己对redis命令还蛮熟悉的,各种数据模型各种基于redis的骚操作.但是最近在使用redis的scan的命令式却踩了一个坑,顿时发觉自己原来对redis的游标理解的很有限.所以记录下这 ...
- Redis Scan迭代器遍历操作原理(一)
Redis在2.8.0版本新增了众望所归的scan操作,从此再也不用担心敲入了keys*, 然后举起双手看着键盘等待漫长的系统卡死了··· 命令的官方介绍在这里, 中文版由huangz同学细心翻译了, ...
- Couchbase集群和Redis集群解析
Couchbase集群和Redis集群解析 首先,关于一些数据库或者是缓存的集群有两种结构,一种是Cluster;一种是master-salve. 关于缓存系统一般使用的就是Redis,Redis是开 ...
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- 超详细的Guava RateLimiter限流原理解析
超详细的Guava RateLimiter限流原理解析 mp.weixin.qq.com 点击上方“方志朋”,选择“置顶或者星标” 你的关注意义重大! 限流是保护高并发系统的三把利器之一,另外两个是 ...
- Redis核心原理
Redis系统介绍: Redis的基础介绍与安装使用步骤:https://www.jianshu.com/p/2a23257af57b Redis的基础数据结构与使用:https://www.jian ...
- ThreadLocal系列(一)-ThreadLocal的使用及原理解析
ThreadLocal系列之ThreadLocal(源码基于java8) 项目中我们如果想要某个对象在程序运行中的任意位置获取到,就需要借助ThreadLocal来实现,这个对象称作线程的本地变量,下 ...
- Redis Scan迭代器遍历操作原理(二)
续上一篇文章 Redis Scan迭代器遍历操作原理(一)–基础 ,这里着重讲一下dictScan函数的原理,其实也就是redis SCAN操作最有价值(也是最难懂的部分). 关于这个算法的源头,来自 ...
随机推荐
- DevOps|我们需要什么样的产研项目管理工具
上一篇文章<DevOps|产研运协作工具链上的皇冠-项目管理工具>主要讲了项目管理工具对软件研发的重要性,本篇文章主要想讲清楚我们需要什么样的项目管理工具,项目管理工具必须具备的功能有哪些 ...
- 零代码搭建一个微信小程序
本文分享自华为云社区<[新手指引]体验通过Astro Zero零代码快速搭建微信小程序>,作者:华为云Astro . 您将学会如何基于Astro零代码能力,DIY开发,完成问卷.投票.信息 ...
- 实战案例丨使用云连接CC和数据复制服务DRS实现跨区域RDS迁移和数据同步
摘要:实践案例展示如何使用云连接CC和数据复制服务DRS实现跨区域RDS迁移和数据同步. [业务场景及诉求] 希望将不同区域"华北-北京四"的rds与"亚太-新加坡&qu ...
- “互联网+”大赛之智慧校园 赛题攻略:你的智慧校园,WeLink帮你来建
摘要:本赛题的核心就是借助华为云WeLink的中台服务能力/开发工具等,结合学校的具体的高价值场景,开发出WeLink小程序,方便师生的学习与生活. 本文分享自华为云社区<"互联网+& ...
- 有了这个告警系统,DBA提前预警不是难题
摘要:告警功能是各大云平台必不可少的模块,个性化的告警配置,为帮助用户和运维人员及时发现问题发挥着重要作用. 本文分享自华为云社区<GaussDB(DWS) 数据库智能监控系统告警框架上线啦!& ...
- 只需2步,教你在Vue中设置登录验证拦截
摘要:两步教你在Vue中设置登录验证拦截! 本文分享自华为云社区<两步教你在Vue中设置登录验证拦截!>,作者: 灰小猿 . 今天在做vue和springboot交互的一个项目的时候,想要 ...
- OpenHarmony移植案例:如何适配服务启动引导部件bootstrap_lite
摘要:本文介绍了startup子系统之bootstrap_lite服务启动引导部件的移植适配案例及原理. 本文分享自华为云社区<OpenHarmony移植案例与原理 - startup子系统之b ...
- IaC 存储最佳实践
往往一些成功的软件公司在构建解决方案的时候十分注重其可重复性.可审计性.和简便性,而基础设施即代码(IaC)的出现让开发人员能够将这些时间应用于基础设施的分配.目前的存储 IaC 的实践有以下三种: ...
- Nginx在windows下常用命令
cmd 进入Nginx解压目录 执行以下命令 start nginx : 启动nginx服务 nginx -s reload :修改配置后重新加载生效 nginx -s reopen :重新打开日志文 ...
- Mac Maven环境变量配置 zsh: command not found: mvn
之前配过环境变量,但是后来打开还是报 zsh: command not found: mvn 需要在运行前先刷下环境变量 source ~/.bash_profile 每次使用前都刷一下比较麻烦,这是 ...