在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命令相关推荐

  1. redis集群搭建及管理命令

    文章目录 1.集群的搭建 1.1 快速搭建集群 1) 首先,我们可以通过执行start命令来创建出6个节点,这6个节点的IP地址都为本机,而端口号则为30001-30006: 2)接着,我们需要使用c ...

  2. 5 数据库缓存机制 redis集群 --SoringBoot整合redis--及redis命令集

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件 1 上传安装包 2 解压Redis tar -xvf redis-5.0.4.tar.gz 3 安 ...

  3. redis集群scan_利用scan迁移部分单点redis数据到RedisCluster

    #!/usr/bin/env python3.7.4#-*- coding:utf-8 -*-#--------------------#File: rds2rdsCluster.py#Project ...

  4. 转:Redis 集群搭建详细指南

    转自: https://www.cnblogs.com/mafly/p/redis_cluster.html [README] 非常棒的一篇文章,感谢作者的分享: 先有鸡还是先有蛋? 最近有朋友问了一 ...

  5. 两台服务器安装redis集群_redis 集群搭建,小白也能搭三主三从的集群环境

    redis集群简介: Redis集群是一个程序集,它提供在多个 Redis节点之间共享数据. 一个 Redis集群不支持同时处理多个键的 Redis命令,因为这要求将数据移动到多个节点之间,这会降低 ...

  6. redis 端口_「建议收藏」手把手教你搭建redis集群

    前言 在生产中单机的redis服务不能保证程序的高可用,所以有时需要我们来搭建一个redis集群,保证某一台redis服务挂了的时候,我们的服务还可以保证正常运行. 单机redis的搭建,可以参考我的 ...

  7. linux集群组建和管理,Redis集群搭建与管理

    集群简介: Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation). Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令 ...

  8. redis 集群 实操 (史上最全、5w字长文)

    文章很长,建议收藏起来慢慢读! 总目录 博客园版 为大家准备了更多的好文章!!!! 推荐:尼恩Java面试宝典(持续更新 + 史上最全 + 面试必备)具体详情,请点击此链接 尼恩Java面试宝典,34 ...

  9. 20、Redis集群Moved重定向与Ask重定向

    1.redis集群一共有16384个虚拟slot,被均匀分配到集群里所有redis机器node上: 2.每个node之间可以互相meet操作,都知道彼此slot范围: 3.客户端向redis集群任意n ...

  10. redis集群moved重定向与redis集群ask重定向

    1.redis集群一共有16384个虚拟slot,被均匀分配到集群里所有redis机器node上: 2.每个node之间可以互相meet操作,都知道彼此slot范围: 3.客户端向redis集群任意n ...

最新文章

  1. 参加Java培训需要注意什么
  2. 坐在马桶上看算法:只有五行的Floyd最短路算法
  3. cdh jar包 sqoop2_安装sqoop1.4.6-cdh5.5.2
  4. cpp判断输入为数字_猜数字小程序带你C语言入门
  5. 在 .NET Core 5 中集成 Create React app
  6. Java的文件流操作
  7. Kubernetes 微服务监控体系
  8. 漫谈广告竞价模式(一)
  9. ~~一般哈希(数据结构)(附模板题AcWing 840 模拟散列表)
  10. [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍
  11. 基于Androidstudio的2048小游戏的设计与实现
  12. vue 显示日期只显示年月_Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示...
  13. 晶闸管的原理及伏安特性
  14. can网络管理(osek中的NM)
  15. 你知道项目管理有哪些分类和体系吗?
  16. 115、神州数码交换机配置基本命令
  17. 发光二极管之二——正负极如何判断
  18. RMS数据采集分布式架构
  19. Cocos Creator三消小游戏(TS 02版)
  20. 密码学系列 - DER编码

热门文章

  1. Mac分区失败导致出现隐藏分区的解决办法
  2. gRPC 流式传输极简入门指南
  3. Java读文件的三种方式
  4. 桥架算量用什么软件_鹏业安装算量软件识别桥架
  5. html渐变编织背景,CSS hover背景/文字渐变效果
  6. arcgis地理配准_Arcgis 地理配准步骤(底图校正)详细讲解
  7. Java金额转换_阿拉伯数字转换成中国大写数字
  8. 猿人学web端爬虫攻防大赛赛题解析_第六题:js 混淆 - 回溯
  9. 自己做网站需要掌握哪些知识?
  10. 蓝牙双模音频模块 BT401蓝牙BLE应用笔记