redis scan 命令指南

1. 模糊查询键值

redis 中模糊查询keykeysscan等,一下是一些具体用法。

-- 命令用法:keys [pattern]
keys name* -- 查询以name开始的key -- 命令用法:scan cursor [match pattern] [COUNT count]
scan 0 match name* 更多命令请参考:http://doc.redisfans.com/key/scan.html

2. keys 注意事项

虽然 keys的速度非常快,但是在一个大的数据库中,使用它还是可能造成性能问题,如果你需要从一个数据集中查找特定的key,你最好还是用 Redis 集合结构(set)来代替。

也就是说,keys 命令在生产环境不可以随便用,因为keys 会锁住 redis,并增加redis 的cpu 占用,所以很多公司的redis都禁用了这个命令。

scan就不会,因为它每次执行只返回少量的元素,所以这个命令可以用于生产环境,而不会像keyssmembers命令一样,当数据库很大时,可能会锁住数秒,这对10000Qps的redis来说是毁灭性的伤害。

3. scan 使用方式

这里使用redisTemplate来执行Redis命令,具体例子如下:

-- 1.单次查询
(ScanPageResult) redisTemplate.execute((RedisCallback<ScanPageResult>) conn -> {
MultiKeyCommands commands = (MultiKeyCommands) conn.getNativeConnection();
ScanParams scanParams = new ScanParams();
scanParams.count(CommonConst.BATCH_SIZE_200);
scanParams.match(pattern);
ScanPageResult result = new ScanPageResult(); ScanResult<String> scanResult = commands.scan(cursor, scanParams);
Set<String> keys = Sets.newHashSet();
if (scanResult.getStringCursor() != null) {
keys.addAll(scanResult.getResult());
if (!"0".equals(scanResult.getStringCursor())) {
result.setNextCursor(scanResult.getStringCursor());
}
}
result.setKeys(keys);
return result;
}); -- ScanPageResult 是自己构造的对象,存储返回的keys和cursor -- 2. 查询所有
do {
result = CacheUtil.scanForPage(pattern, result.getNextCursor());
if (result == null) {
break;
}
Set<String> keys = result.getKeys();
doSomething(keys);
} while (!"0".equals(result.getNextCursor()));

稍微解释一下,因为scan命令只会返回少量数据,而不是所有数据,所以它还需要返回一个:记录上次查询到的位置标识,这个在redis里被称为cursor(游标)。

所以下次再次查询的时候需要传入上一次返回的cursor继续查询,直到cursor=0为止,标识迭代结束,查询完毕。

一般第一次查询传入的cursor=0,作为初始查询,然后根据结果判断是否进行下一次查询。

3.1 scan 命令的保证

因为是增量式迭代查询,以保证查询所有的结果,所以,在查询间隔中新增的key,不一定会被返回。

另外,因为新增或删除key都会改变redis key的索引,所以,多次查询也会有重复的元素出现,所以使用scan命令,一定需要保证业务处理可重复执行

然而因为增量式命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点:

同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。

如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义的(undefined)。

3.2 并发执行多个迭代

在同一时间, 可以有任意多个客户端对同一数据集进行迭代, 客户端每次执行迭代都需要传入一个游标, 并在迭代执行之后获得一个新的游标, 而这个游标就包含了迭代的所有状态, 因此, 服务器无须为迭代记录任何状态。

3.3 使用错误的游标进行增量式迭代

使用间断的(broken)、负数、超出范围或者其他非正常的游标来执行增量式迭代并不会造成服务器崩溃, 但可能会让命令产生未定义的行为。

未定义行为指的是, 增量式命令对返回值所做的保证可能会不再为真。

只有两种游标是合法的

  • 在开始一个新的迭代时, 游标必须为 0 。
  • 增量式迭代命令在执行之后返回的, 用于延续(continue)迭代过程的游标。

4. 参考

scan 命令

在RedisTemplate中使用scan代替keys指令

用redis的scan命令代替keys命令,以及在spring-data-redis中遇到的问题

redis scan 命令指南的更多相关文章

  1. Redis Scan命令

    原地址:https://www.cnblogs.com/tekkaman/p/4887293.html [Redis Scan命令] SCAN cursor [MATCH pattern] [COUN ...

  2. redis scan命令使用

      以前的项目中有用到redis的keys命令来获取某些key,知道看了这篇文章 https://mp.weixin.qq.com/s/SGOyGGfA6GOzxwD5S91hLw.安全起见,这次打算 ...

  3. Redis SCAN命令实现有限保证的原理

    SCAN命令可以为用户保证:从完整遍历开始直到完整遍历结束期间,一直存在于数据集内的所有元素都会被完整遍历返回,但是同一个元素可能会被返回多次.如果一个元素是在迭代过程中被添加到数据集的,又或者是在迭 ...

  4. 用redis的scan命令代替keys命令,以及在spring-data-redis中遇到的问题

    摘要 本文主要是介绍使用redis scan命令遇到的一些问题总结,scan命令本身没有什么问题,主要是spring-data-redis的问题. 需求 需要遍历redis中key,找到符合某些pat ...

  5. Redis中的Scan命令的使用

    Redis中有一个经典的问题,在巨大的数据量的情况下,做类似于查找符合某种规则的Key的信息,这里就有两种方式,一是keys命令,简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行 ...

  6. Redis中的Scan命令踩坑记

    1 原本以为自己对redis命令还蛮熟悉的,各种数据模型各种基于redis的骚操作.但是最近在使用redis的scan的命令式却踩了一个坑,顿时发觉自己原来对redis的游标理解的很有限.所以记录下这 ...

  7. redis 迭代命令SCAN、SSCAN、HSCAN、ZSCAN

    SCAN 命令用于迭代当前数据库中的数据库键.SSCAN 命令用于迭代集合键中的元素.HSCAN 命令用于迭代哈希键中的键值对.ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值). S ...

  8. redis 《scan命令》

    此命令十分奇特建议参考文档:http://redisdoc.com/database/scan.html#scan     222222222222222并非每次迭代都要使用相同的 COUNT 值. ...

  9. Redis常用命令

    Redis常用命令Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以再Linux终端使用.1.键值相关命令2.服务器相关命令 一.键值相关命令 1.get get 键值 当 key ...

随机推荐

  1. 交换机Access、Trunk和Hybrid 接口类型及区别

    交换机接口的类型可以是 Access.Trunk和Hybrid. Access类型的接口仅属于一个VLAN,只能接收.转发相应VLAN的帧: Trunk类型接口则默认属于所有VLAN,任何 Tagge ...

  2. 使用 IDEA 创建多模块项目

    网上找如何创建多模块项目的资料,大多类似,实践中又各有问题,此文为摸索之后总结 最终项目结构如下: 项目引用关系:app → service → dao 新建父项目 multi-parent mult ...

  3. 编写测试用例 QQ账号6--10位自然数 某城市电话号码 126邮箱注册功能

  4. MVTMVC 区别

    1,MVC的意思是 M:model V:views C:controller model是  主要是封装对数据库层的访问,对数据库中的数据进行增删改查操作 views 是 用于封装结果, 生程页面展示 ...

  5. 使用PyQt(Python+Qt)+动态编译36行代码实现的计算器

    PyQt是基于跨平台的图形界面C++开发工具Qt加Python包装的一个GPL软件(GPL是GNU General Public License的缩写,是GNU通用公共授权非正式的中文翻译),Qt基于 ...

  6. Azure Cosmos DB (五) .Net Core 控制台应用

    一,引言 之前在讲Azure CosmosDB Core(SQL)核心的时候,使用了EF Core 的方式,引用了 "Microsoft.EntityFrameworkCore.Cosmos ...

  7. python基本案例实现

    案例一:test.txt文件中与输入的用户进行认证,超过3次用户被锁定,且把用户加入锁定的lock.txt文件中. # 需求点: # 1.输入用户名.密码 # 2.认证成功后显示欢迎信息 # 3.输错 ...

  8. LeetCode初级算法之数组:350 两个数组的交集 II

    两个数组的交集 II 题目地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/ 给定两个数组,编写一个函数来计算它们的交 ...

  9. REHの收藏列表

    搬运自本人的AcWing,所以那里的文章会挺多. 友链(同类文章) :bztMinamoto 世外明月 mlystdcall 新人手册:AcWing入门使用指南 前言 有看到好文欢迎推荐(毛遂自荐也可 ...

  10. 【Luogu P5168】xtq玩魔塔(Kruskal 重构树 & 树状数组 & set)

    Description 给定一个 \(n\) 个顶点,\(m\) 条边的无向联通图,点.边带权. 先有 \(q\) 次修改或询问,每个指令形如 \(\text{opt}\ x\ y\): \(\tex ...