[转帖]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操作最有价值(也是最难懂的部分). 关于这个算法的源头,来自 ...
随机推荐
- 在Docker上面安装/启动、运行、挂载MySQL5.7
下载文档请看:https://hub.docker.com/r/mysql/mysql-server 一.下载镜像 执行命令: docker pull mysql/mysql-server:5.7 查 ...
- Spark Streaming快速入门
Spark Streaming快速入门 一.简介 Spark Streaming 是构建在 Spark Core 基础之上的流处理框架(但实际上是微批次处理框架),是 Spark 非常重要的组成部分. ...
- KubeEdge在边缘计算领域的安全防护及洞察
摘要:着重介绍Kubeedge在安全防护方面的实践,并介绍OpenSSF在开源软件安全方面的计划与目标. 本文分享自华为云社区<KubeEdge在边缘计算领域的安全防护及洞察>,作者:华为 ...
- CSV:简单格式下隐藏的那些坑
摘要:本文将盘点处理CSV数据时我遇到的一些坑. 本文分享自华为云社区<CSV-简单格式下隐藏的那些坑>,作者:aKi. 前言 CSV(Comma-Separated Values),是一 ...
- ROMA集成关键技术:增量数据集成
摘要:本文将详解ROMA集成关键技术-增量数据集成技术. 本文分享自华为云社区<ROMA集成关键技术(2)-增量数据集成技术>,作者:华为云PaaS服务小智 . 1.概述 ROMA平台的核 ...
- 养殖场新来了个“AI管家”
摘要:定制化算法+端侧一键部署,打通AI全流程. 本文分享自华为云社区<[云享·伙伴]第4期:养殖场新来了个"AI管家">,作者: 华为云社区精选. 民以食为天.肉类是 ...
- Vuex在TSX中的改造方案:TS改造Vue2项目Vuex如何处置?
vuex目前比较流行的有:vuex-aggregate . vuex-class.vuex-module-decorators npm搜到相关的,看下趋势图:https://www.npmtrends ...
- 火山引擎 DataLeap 下 Notebook 系列文章二:技术路线解析
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 在 Jupyter 的生态下,除了 Notebook 本身,火山引擎 DataLeap 研发团队还注意到了很多其他 ...
- compilation.templatesPlugin is not a function
ERROR Failed to compile with 1 error TypeError: compilation.templatesPlugin is not a function - SetV ...
- 叫板GPT-4的Gemini,我做了一个聊天网页,可图片输入,附教程
先看效果: 简介 Gemini 是谷歌研发的最新一代大语言模型,目前有三个版本,被称为中杯.大杯.超大杯,Gemini Ultra 号称可与GPT-4一较高低: Gemini Nano(预览访问) 为 ...