`
m635674608
  • 浏览: 5041987 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

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代码  收藏代码
  1. val jedisCluster = new JedisCluster(hostPorts)  
  2.    
  3.     val clusterNodes = jedisCluster.getClusterNodes.values()  
  4.     for (clusterNode: JedisPool <- clusterNodes) {  
  5.       var scanCursor = "0"  
  6.       val resource: Jedis = clusterNode.getResource  
  
 
在每个节点上执行scan命令,scan命令的结束条件并不是只有返回下个index=0,也有可能得到的列表为空,此时同样宣告没有新的key了。
 
此时就可以通过一个do/while循环来进行scan操作:
 
Java代码  收藏代码
  1. for (clusterNode: JedisPool <- clusterNodes) {  
  2.       var scanCursor = "0"  
  3.       var scanResult: util.List[String] = new util.ArrayList[String]()  
  4.       do {  
  5.         val resource: Jedis = clusterNode.getResource  
  6.         val scan: ScanResult[String] = resource.scan(scanCursor, new ScanParams().`match`(“xxx*"))  
  7.         scanCursor = scan.getStringCursor  
  8.         scanResult = scan.getResult  
  9.         for (key: String <- scanResult) {  
  10.           //xxx  
  11.         }  
  12.         resource.close()  
  13.       } while (!scanCursor.equals("0") && !scanResult.isEmpty)  
  14.     }  
 
 
 
scan时可以设置count(数量)以及match(匹配模式),以便于按照条件进行过滤。
 
 
但需要统计一下通过scan方法执行出来的键值总结果是否与keys执行结果相同(在相同的运行条件下,redis不能随意增加key)。
 
经过我们的验证,在cluster模式下,将所有key放到set下(考虑到master/slave键重复,cluster模式下keys会忽略重复的键,但是每个redis连接进行scan却不会)是相同的:
 
Java代码  收藏代码
  1. val keys = new mutable.HashSet[String]()  
  2.     for (clusterNode: JedisPool <- clusterNodes) {  
  3.       var scanCursor = "0"  
  4.       var scanResult: util.List[String] = new util.ArrayList[String]()  
  5.       do {  
  6.         val resource: Jedis = clusterNode.getResource  
  7.         val scan: ScanResult[String] = resource.scan(scanCursor, new ScanParams().`match`(PROD_SKU_PRICE + "*"))  
  8.         scanCursor = scan.getStringCursor  
  9.         scanResult = scan.getResult  
  10.         for (key: String <- scanResult) {  
  11.           keys.add(key)  
  12.         }  
  13.         resource.close()  
  14.       } while (!scanCursor.equals("0") && !scanResult.isEmpty)  
  15.     }  
  16.     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代码  收藏代码
  1. public ScanResult<String> scan(final String hashTag, final String cursor, final ScanParams params) {  
  2.     ZhenQueryContextHolder.getInstance().setQueryContext(new ZhenQueryContext(OperationType.READ));  
  3.     return new ZhenJedisClusterCommand<ScanResult<String>>(connectionHandler, maxRedirections) {  
  4.    
  5.         @Override  
  6.         public ScanResult<String> execute(Jedis connection) {  
  7.             return connection.scan(cursor, params);  
  8.         }  
  9.     }.run(hashTag);  
  10. }  
 
 
参考: 
 
分享到:
评论

相关推荐

    25_你能聊聊redis cluster集群模式的原理吗?.zip

    3. 不支持某些命令,如:Keys、Scan等全局扫描命令,因为它们可能涉及跨多个节点的操作。 4. 考虑到网络延迟和通信开销,建议将Redis Cluster的节点部署在同一地区,以降低延迟并提高性能。 总结,Redis Cluster...

    redis cluster介绍.rar

    2. 避免使用需要跨节点操作的命令,如`KEYS`、`SCAN`、`FLUSHDB`和`FLUSHALL`,因为它们可能影响性能和数据一致性。 3. 为每个主节点配置至少一个从节点,提高可用性和容错性。 4. 监控网络延迟,避免网络分区导致的...

    Redis集群数据迁移操作文档

    启动命令的基本格式是`redis-shake.linux -conf=redis-shake.conf -type=xxx`,其中`xxx`代表迁移模式,包括sync(全量+增量同步)、dump(数据备份到RDB文件)、decode(解析RDB文件)、restore(从RDB恢复到Redis...

    Redis从入门到精通2024版 视频教程 下载 百度网盘链接4.zip

    Redis从入门到精通2024版 视频教程 下载 ├─第 01 章 开篇 │ 001.Redis 录制计划.mp4 │ 002.Redis 介绍.mp4 │ 003.Redis 安装.mp4 ...│ 01....│ 02....│ 03....│ 04....│ 05....│ 20.RedisCluster

    Redis从入门到精通2024版 视频教程 下载 百度网盘链接3.zip

    Redis从入门到精通2024版 视频教程 下载 ├─第 01 章 开篇 │ 001.Redis 录制计划.mp4 │ 002.Redis 介绍.mp4 │ 003.Redis 安装.mp4 ...│ 01....│ 02....│ 03....│ 04....│ 05....│ 20.RedisCluster

    Redis从入门到精通2024版 视频教程 下载 百度网盘链接1.zip

    Redis从入门到精通2024版 视频教程 下载 ├─第 01 章 开篇 │ 001.Redis 录制计划.mp4 │ 002.Redis 介绍.mp4 │ 003.Redis 安装.mp4 ...│ 01....│ 02....│ 03....│ 04....│ 05....│ 20.RedisCluster

    Redis从入门到精通2024版 视频教程 下载 百度网盘链接2.zip

    Redis从入门到精通2024版 视频教程 下载 ├─第 01 章 开篇 │ 001.Redis 录制计划.mp4 │ 002.Redis 介绍.mp4 │ 003.Redis 安装.mp4 ...│ 01....│ 02....│ 03....│ 04....│ 05....│ 20.RedisCluster

    Redis+模糊匹配+批量上传+Keys

    模糊匹配在Redis中主要通过`KEYS`和`SCAN`命令来实现。`KEYS`命令可以查找符合特定模式的所有键,例如,`KEYS *pattern*`将返回所有与`pattern`匹配的键。然而,由于`KEYS`在大型数据库中可能导致性能问题,因此推荐...

    redis-3.0.0&redis;-3.0.0.gem.zip

    - 数据分布:Redis Cluster自动将数据分散在多个节点上,但并非所有命令都支持集群模式,如`KEYS`和`SCAN`命令。 - 故障转移:当主节点出现故障时,从节点会自动接管,确保服务的连续性。 - 网络分区处理:在...

    REDIS命令文档网页离线版

    此外,`KEYS`和`SCAN`命令用于查找匹配模式的键,`FLUSHALL`和`FLUSHDB`则清除所有数据库或当前数据库的数据。 集群方面,Redis支持主从复制和自动故障转移,通过`SLAVEOF`命令设置节点为其他节点的副本。最新版本...

    redis命令实践.zip

    2. 集群:Redis Cluster提供了分布式部署能力,可将数据自动分片到多个节点,提供高可用性和扩展性。 六、其他命令 - `INCR`和`DECR`用于原子地增加或减少整数值。 - `TTL`和`PEXPIRE`用于查看或设置键的过期时间...

    Redis命令参考手册完整版 中文PDF版.rar_Redis 入门操作_redis pdf_redis.pdf_redis中文

    - 命令优化:避免使用高开销的命令,如`KEYS`,改用`SCAN`进行遍历。 - 使用连接池:减少建立和断开连接的开销。 七、安全与监控 - 认证:启用`requirepass`配置项,为Redis服务器设置密码。 - 监控:使用`INFO`...

    java 对Redis的导入和导出

    可以使用`SCAN`命令代替,以增量方式遍历键。同时,数据传输过程中应确保数据安全,可采用加密等手段。 6. **扩展性**: 如果需要在多台Redis服务器间迁移数据,可以将上述逻辑封装为一个服务,通过消息队列或定时...

    redis基本命令aper-开发笔记

    - Redis集群提供数据分片和故障转移,使用`CLUSTER NODES`查看节点信息,`CLUSTER ADDSLOTS`分配槽位,`CLUSTER MEET`添加新节点。 了解并熟练掌握这些Redis基本命令,能帮助开发者高效地利用Redis处理各种数据...

    redis面试题之单线程.zip

    对于耗时的计算任务,如排序或求交集,Redis提供了一些优化策略,如`KEYS`命令的慎用、`SCAN`命令的使用,以及Lua脚本的执行,以减少单线程的阻塞时间。 四、面试题解析 4.1 Redis为何选择单线程模型? 答:Redis...

    redis缓存工具

    同时,了解如何使用`EXPIRE`命令设置键的过期时间,以及`KEYS`、`SCAN`命令来查找和管理键也是很重要的。 总之,Redis作为一款强大的缓存工具,提供了丰富的功能和高效的数据处理能力。理解其核心概念、安装流程、...

    60道关于Redis的常见面试题.pdf

    - **定义**:Pipeline 允许客户端将多个命令打包发送给 Redis 服务器,然后一次性接收所有命令的结果。 - **提高性能**: - 减少了网络往返次数。 - 提高了客户端与服务器间的数据传输效率。 #### 12. 在使用 ...

    redis container 问题梳理

    2. **命令执行效率**:某些命令如`KEYS`和`SCAN`在大数据量下可能导致服务器阻塞。应尽量避免使用这些命令,转而使用更安全的替代方案。 3. **网络延迟**:网络连接质量对Redis性能有显著影响。可以考虑使用连接池...

    最全php_redis,从2.2.7到4.2.0

    - 新特性:新增了`scan`命令,用于无阻塞地迭代键空间;增加了`pipeline`和`transaction`方法,提升批量操作效率。 4. PHP Redis 4.2.0 - 这个版本继续增强对Redis新特性的支持,如Stream数据类型。 - 优化:...

    一个灵活且功能齐全的 PHP Redis 客户端 .zip

    支持redis-cluster(Redis &gt;= 3.0)。支持主从复制设置和redis-sentinel。使用可定制的前缀策略对键进行透明的键前缀处理。单节点和集群上的命令流水线(仅限客户端分片)。Redis 事务(Redis &gt;= 2.0)和 CAS 操作...

Global site tag (gtag.js) - Google Analytics