面试突击 | Redis 如何从海量数据中查询出某一个 Key?附视频
1 考察知识点
本题考察的知识点有以下几个:
- Keys 和 Scan 的区别
- Keys 查询的缺点
- Scan 如何使用?
- Scan 查询的特点
2 解答思路
- Keys 查询存在的问题
- Scan 的使用
- Scan 的特点
3 Keys 使用相关
1)Keys 用法如下
2)Keys 存在的问题
- 此命令没有分页功能,我们只能一次性查询出所有符合条件的 key 值,如果查询结果非常巨大,那么得到的输出信息也会非常多;
- keys 命令是遍历查询,因此它的查询时间复杂度是 o(n),所以数据量越大查询时间就越长。
4 Scan 使用相关
我们先来模拟海量数据,使用 Pipeline 添加 10w 条数据,Java 代码实现如下:
import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import utils.JedisUtils; public class ScanExample { public static void main(String[] args) { // 添加 10w 条数据 initData(); } public static void initData(){ Jedis jedis = JedisUtils.getJedis(); Pipeline pipe = jedis.pipelined(); for (int i = 1; i < 100001; i++) { pipe.set("user_token_" + i, "id" + i); } // 执行命令 pipe.sync(); System.out.println("数据插入完成"); } }
我们来查询用户 id 为 9999* 的数据,Scan 命令使用如下:
127.0.0.1:6379> scan 0 match user_token_9999* count 10000 1) "127064" 2) 1) "user_token_99997" 127.0.0.1:6379> scan 127064 match user_token_9999* count 10000 1) "1740" 2) 1) "user_token_9999" 127.0.0.1:6379> scan 1740 match user_token_9999* count 10000 1) "21298" 2) 1) "user_token_99996" 127.0.0.1:6379> scan 21298 match user_token_9999* count 10000 1) "65382" 2) (empty list or set) 127.0.0.1:6379> scan 65382 match user_token_9999* count 10000 1) "78081" 2) 1) "user_token_99998" 2) "user_token_99992" 127.0.0.1:6379> scan 78081 match user_token_9999* count 10000 1) "3993" 2) 1) "user_token_99994" 2) "user_token_99993" 127.0.0.1:6379> scan 3993 match user_token_9999* count 10000 1) "13773" 2) 1) "user_token_99995" 127.0.0.1:6379> scan 13773 match user_token_9999* count 10000 1) "47923" 2) (empty list or set) 127.0.0.1:6379> scan 47923 match user_token_9999* count 10000 1) "59751" 2) 1) "user_token_99990" 2) "user_token_99991" 3) "user_token_99999" 127.0.0.1:6379> scan 59751 match user_token_9999* count 10000 1) "0" 2) (empty list or set)
从以上的执行结果,我们看出两个问题:
- 查询的结果为空,但游标值不为 0,表示遍历还没结束;
- 设置的是 count 10000,但每次返回的数量都不是 10000,且不固定,这是因为 count 只是限定服务器单次遍历的字典槽位数量 (约等于),而不是规定返回结果的 count 值。
相关语法:scan cursor [MATCH pattern] [COUNT count]
其中:
- cursor:光标位置,整数值,从 0 开始,到 0 结束,查询结果是空,但游标值不为 0,表示遍历还没结束;
- match pattern:正则匹配字段;
- count:限定服务器单次遍历的字典槽位数量 (约等于),只是对增量式迭代命令的一种提示 (hint),并不是查询结果返回的最大数量,它的默认值是 10。
5 Scan 代码实战
本文我们使用 Java 代码来实现 Scan 的查询功能,代码如下:
import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import utils.JedisUtils; public class ScanExample { public static void main(String[] args) { Jedis jedis = JedisUtils.getJedis(); // 定义 match 和 count 参数 ScanParams params = new ScanParams(); params.count(10000); params.match("user_token_9999*"); // 游标 String cursor = "0"; while (true) { ScanResult<String> res = jedis.scan(cursor, params); if (res.getCursor().equals("0")) { // 表示最后一条 break; } cursor = res.getCursor(); // 设置游标 for (String item : res.getResult()) { // 打印查询结果 System.out.println("查询结果:" + item); } } } }
以上程序执行结果如下:
查询结果:user_token_99997
查询结果:user_token_9999
查询结果:user_token_99996
查询结果:user_token_99998
查询结果:user_token_99992
查询结果:user_token_99994
查询结果:user_token_99993
查询结果:user_token_99995
查询结果:user_token_99990
查询结果:user_token_99991
查询结果:user_token_99999
6 总结
通过本文我们了解到,Redis 中如果要在海量的数据数据中,查询某个数据应该使用 Scan,Scan 具有以下特征:
- Scan 可以实现 keys 的匹配功能;
- Scan 是通过游标进行查询的不会导致 Redis 假死;
- Scan 提供了 count 参数,可以规定遍历的数量;
- Scan 会把游标返回给客户端,用户客户端继续遍历查询;
- Scan 返回的结果可能会有重复数据,需要客户端去重;
- 单次返回空值且游标不为 0,说明遍历还没结束;
- Scan 可以保证在开始检索之前,被删除的元素一定不会被查询出来;
- 在迭代过程中如果有元素被修改, Scan 不保证能查询出相关的元素。
7 视频版
视频内容如下:https://www.bilibili.com/video/av88076985/
关注下面二维码,订阅更多精彩内容。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
How to test Delta download in CRM Side
Subject: How to test Delta download in CRM Side Select one product in CRM side ( QD3/504 ) which you would like to test. The product must have already been downloaded from ERP successfully. In this case I choose product ZJERRYERP1, whose description is "test material". go to ERP system, tcode MM02, make changes on material, for example change its description: After successful save, the change should be immediately synchronized to CRM side. However, since QD3/QDD is the central test system and pe...
- 下一篇
Bertelsmann Arvato 邮购公司客户细分和预测
1. 介绍 1.1 项目概述 在商业直销活动中,使用标签化的用户模型对进行营销活动进行优化是实现精准营销的一个重要工具。本项目要求根据一家德国邮购公司已有客户的人口学特征数据,使用非监督学习技术来分析公司现有顾客的主要特征。然后利用监督学习技术搭建预测模型,在德国的总人口统计数据集上预测新客户。这篇文章是与贝塔斯曼 Arvato Analytics 合作提供的优达学城数据科学家纳米学位毕业项目的一部分。项目中的数据由贝塔斯曼子公司Arvato Financial Solutions提供。 项目分为三个主要步骤:客户细分报告、监督学习模型和Kaggle竞争: 现有客户细分报告:采用EDA、PCA和聚类分析的方法对总体和客户群进行分析,目的是能够描述公司的核心客户群。 新客户的预测报告(监督学习):使用在第一步中观察到的内容创建一个监督学习模型,用其预测一个人是否会响应邮件营销活动。 Kaggle 比赛: 在营销活动的人口统计数据集上预测新客户 1.2. 问题描述 根据Arvato Financial Solutions 的高级大客户经理Time Reis的说法,该项目要解决的基本商业问题...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8编译安装MySQL8.0.19
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题