redis集群scan_RedisCluster的scan命令
在redis中是支持使用通配符的使用,例如‘?’或是’’,所以我们在获取redis里面的某个db里面的所有数据可以用 `keys `这样的指令来实现。但是存在一个问题就是这样做的话,在数据量很大的情况下效率是很不理想的,一般情况下redis的slowlog中总会少不了keys xxx这种类型操作(如果有人在其上面执行该操作的话)
scan命令可以帮助我们解决使用keys命令遍历大量数据而导致服务器阻塞的情况,它每次都只遍历一小部分数据,每次操作对应的时间复杂度为O(1)。
scan命令是一个基于游标(Cursor)的迭代器,scan命令每次被调用之后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为scan命令的游标参数,延续之前的迭代过程。当scan命令的游标参数被设置成0时,服务器将会开始一次新的迭代,当服务器向用户返回的游标值为0时,表示迭代已经结束。
但对于RedisCluster来说,是不可以对所有键进行scan操作的,但可以针对其他数据类型,比如hash, zset,进行一系列hscan,zscan操作。其实可以从jedisCluster的实现可以看出,如果要对所有key进行scan,需要实现MultiKeyCommands,但RedisCluster是不支持这类型操作的,同理pipeline,mget,mset等操作。
但在redisCluster中可以通过getClusterNodes获取每个节点的连接,依次进行遍历并查询:
Java代码
val jedisCluster = new JedisCluster(hostPorts)
val clusterNodes = jedisCluster.getClusterNodes.values()
for (clusterNode: JedisPool
var scanCursor = "0"
val resource: Jedis = clusterNode.getResource
在每个节点上执行scan命令,scan命令的结束条件并不是只有返回下个index=0,也有可能得到的列表为空,此时同样宣告没有新的key了。
此时就可以通过一个do/while循环来进行scan操作:
Java代码
for (clusterNode: JedisPool
var scanCursor = "0"
var scanResult: util.List[String] = new util.ArrayList[String]()
do {
val resource: Jedis = clusterNode.getResource
val scan: ScanResult[String] = resource.scan(scanCursor, new ScanParams().`match`(“xxx*"))
scanCursor = scan.getStringCursor
scanResult = scan.getResult
for (key: String
//xxx
}
resource.close()
} while (!scanCursor.equals("0") && !scanResult.isEmpty)
}
scan时可以设置count(数量)以及match(匹配模式),以便于按照条件进行过滤。
但需要统计一下通过scan方法执行出来的键值总结果是否与keys执行结果相同(在相同的运行条件下,redis不能随意增加key)。
经过我们的验证,在cluster模式下,将所有key放到set下(考虑到master/slave键重复,cluster模式下keys会忽略重复的键,但是每个redis连接进行scan却不会)是相同的:
Java代码
val keys = new mutable.HashSet[String]()
for (clusterNode: JedisPool
var scanCursor = "0"
var scanResult: util.List[String] = new util.ArrayList[String]()
do {
val resource: Jedis = clusterNode.getResource
val scan: ScanResult[String] = resource.scan(scanCursor, new ScanParams().`match`(PROD_SKU_PRICE + "*"))
scanCursor = scan.getStringCursor
scanResult = scan.getResult
for (key: String
keys.add(key)
}
resource.close()
} while (!scanCursor.equals("0") && !scanResult.isEmpty)
}
print (keys.size)
经过验证,总数量是相同的,通过本次测试同时也发现,scan命令的count不会每次真的返回该数量的key值(尽管后续还存在),只会返回比count值小的键值数量。
但考虑到在RedisCluster模式下并不能应用scan命令,我们可以对该命令进行一定的改造,使其能够支持按照hash tag进行操作。由于有着同样hash tag的键都会存放在同一个redis节点上,此时仅针对RedisCluster中的单个redis连接操作即可,有点类似之前说过的读写分离方案: http://brandnewuser.iteye.com/blog/2315636 ,直接在之前的方案中,增加scan方法(继承的JedisCluster类中),由于该操作中没有对应的key,因此需要额外传递hashTag用来指定使用到哪个节点来处理:
Java代码
public ScanResult scan(final String hashTag, final String cursor, final ScanParams params) {
ZhenQueryContextHolder.getInstance().setQueryContext(new ZhenQueryContext(OperationType.READ));
return new ZhenJedisClusterCommand>(connectionHandler, maxRedirections) {
public ScanResult execute(Jedis connection) {
return connection.scan(cursor, params);
}
}.run(hashTag);
}
参考:
redis集群scan_RedisCluster的scan命令相关推荐
- redis集群搭建及管理命令
文章目录 1.集群的搭建 1.1 快速搭建集群 1) 首先,我们可以通过执行start命令来创建出6个节点,这6个节点的IP地址都为本机,而端口号则为30001-30006: 2)接着,我们需要使用c ...
- 5 数据库缓存机制 redis集群 --SoringBoot整合redis--及redis命令集
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件 1 上传安装包 2 解压Redis tar -xvf redis-5.0.4.tar.gz 3 安 ...
- redis集群scan_利用scan迁移部分单点redis数据到RedisCluster
#!/usr/bin/env python3.7.4#-*- coding:utf-8 -*-#--------------------#File: rds2rdsCluster.py#Project ...
- 转:Redis 集群搭建详细指南
转自: https://www.cnblogs.com/mafly/p/redis_cluster.html [README] 非常棒的一篇文章,感谢作者的分享: 先有鸡还是先有蛋? 最近有朋友问了一 ...
- 两台服务器安装redis集群_redis 集群搭建,小白也能搭三主三从的集群环境
redis集群简介: Redis集群是一个程序集,它提供在多个 Redis节点之间共享数据. 一个 Redis集群不支持同时处理多个键的 Redis命令,因为这要求将数据移动到多个节点之间,这会降低 ...
- redis 端口_「建议收藏」手把手教你搭建redis集群
前言 在生产中单机的redis服务不能保证程序的高可用,所以有时需要我们来搭建一个redis集群,保证某一台redis服务挂了的时候,我们的服务还可以保证正常运行. 单机redis的搭建,可以参考我的 ...
- linux集群组建和管理,Redis集群搭建与管理
集群简介: Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation). Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令 ...
- redis 集群 实操 (史上最全、5w字长文)
文章很长,建议收藏起来慢慢读! 总目录 博客园版 为大家准备了更多的好文章!!!! 推荐:尼恩Java面试宝典(持续更新 + 史上最全 + 面试必备)具体详情,请点击此链接 尼恩Java面试宝典,34 ...
- 20、Redis集群Moved重定向与Ask重定向
1.redis集群一共有16384个虚拟slot,被均匀分配到集群里所有redis机器node上: 2.每个node之间可以互相meet操作,都知道彼此slot范围: 3.客户端向redis集群任意n ...
- redis集群moved重定向与redis集群ask重定向
1.redis集群一共有16384个虚拟slot,被均匀分配到集群里所有redis机器node上: 2.每个node之间可以互相meet操作,都知道彼此slot范围: 3.客户端向redis集群任意n ...
最新文章
- 参加Java培训需要注意什么
- 坐在马桶上看算法:只有五行的Floyd最短路算法
- cdh jar包 sqoop2_安装sqoop1.4.6-cdh5.5.2
- cpp判断输入为数字_猜数字小程序带你C语言入门
- 在 .NET Core 5 中集成 Create React app
- Java的文件流操作
- Kubernetes 微服务监控体系
- 漫谈广告竞价模式(一)
- ~~一般哈希(数据结构)(附模板题AcWing 840 模拟散列表)
- [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍
- 基于Androidstudio的2048小游戏的设计与实现
- vue 显示日期只显示年月_Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示...
- 晶闸管的原理及伏安特性
- can网络管理(osek中的NM)
- 你知道项目管理有哪些分类和体系吗?
- 115、神州数码交换机配置基本命令
- 发光二极管之二——正负极如何判断
- RMS数据采集分布式架构
- Cocos Creator三消小游戏(TS 02版)
- 密码学系列 - DER编码