Redis Cluster 字段模糊匹配及删除


Posted in Redis onMay 27, 2021

Questions

在数据库内我们可以通过like关键字、%、*或者REGEX关键字进行模糊匹配。而在Redis内我们如何进行模糊匹配呢?集群情况Redis Cluster的情况是否和单机一致呢?前段时间我对于这个议题进行了调查和研究。

单节点的情况

Jedis
参考stackoverflow上的解答,在Java内使用Jedis主要有如下2中写法:

### 方法1
Set<String> keys = jedis.keys(pattern);
for (String key : keys) {
    jedis.del(key);
} 

### 方法2
Jedis jedis = new Jedis("127.0.0.1");
ScanParams scanParams = new ScanParams();
scanParams.match("prifix*");
scanParams.count(1000);
ScanResult<String> result = jedis.scan(0,scanParams);
result.getResult().forEach(key -> {
    jedis.del(key);
});

### 注意scan方法由于某些bug在2.9版本内scan(int,ScanParams)改为了scan(String,ScanParams)。由于cursor的位数,方法有些调整。

方法1,通过keys命令先寻找到所有符合的key,然后把它们删除;
方法2,通过scan命令扫描所有符合的key,然后把它们删除。
注意: Redis饰单线程模式,全局扫描的话有可能会导致Redis在一段时间内的卡顿情况发生。

Redis-cli

redis-cli keys 1.cn*|xargs redis-cli del

Redis Cluster情况

在Redis Cluster情况与单节点多情况完全不太一样。

  • 首先,Redis Cluster是将整个Redis 的hash槽分布在三台机器上,要想一下全部扫描出来,显然是不太现实的。
  • Redis内提供Hash-Tag,将相类似的键放在一台机器上。可以通过Hash-Tag进行扫描,可以剪短时间消耗。
  • 最后需要考虑,主从集群节点的情况。

Hash-Tag

Hash-Tag 是用一个花括号将主要的Hash判断部分扩起来,例如{hello1}key1、{hello1}key2。一般Hash-tag一致的情况,键会存储在集群的同一台机器上。在Jedis 2.9版本提供了这样的扫描方法。
(PS . rediscluster是没有keys方法的)

public static void deleteRedisKeyStartWith(String redisKeyStartWith) {
        try{
            jedisCluster.getClusterNodes();

            ScanParams scanParams = new ScanParams();
//          scanParams.match("{123}keys*");

//          scanParams.count(1000);
            ScanResult<String> result = jedisCluster.scan("0", scanParams);
            result.getResult().forEach(key -> {
                jedisCluster.del(key);
            });
//          jedisCluster.del(wrapperKey(redisKeyStartWith)+".*");
            log.info("success deleted redisKeyStartWith:{}", redisKeyStartWith);
        }finally{
        }
    }

土办法 分别扫描各个hash槽

public static void deleteRedisKeyStartWith(String redisKeyStartWith) {
        try {
            Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();

            for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {
                Jedis jedis = entry.getValue().getResource();
                // 判断非从节点(因为若主从复制,从节点会跟随主节点的变化而变化)
                if (!jedis.info("replication").contains("role:slave")) {
                    Set<String> keys = jedis.keys(redisKeyStartWith + "*");
                    if (keys.size() > 0) {
                        Map<Integer, List<String>> map = new HashMap<>();
                        for (String key : keys) {
                            // cluster模式执行多key操作的时候,这些key必须在同一个slot上,不然会报:JedisDataException:
                            // CROSSSLOT Keys in request don't hash to the same slot
                            int slot = JedisClusterCRC16.getSlot(key);
                            // 按slot将key分组,相同slot的key一起提交
                            if (map.containsKey(slot)) {
                                map.get(slot).add(key);
                            } else {
                                map.put(slot, Lists.newArrayList(key));
                            }
                        }
                        for (Map.Entry<Integer, List<String>> integerListEntry : map.entrySet()) {
                            jedis.del(integerListEntry.getValue().toArray(new String[integerListEntry.getValue().size()]));
                        }
                    }
                }
            }
            log.info("success deleted redisKeyStartWith:{}", redisKeyStartWith);
        } finally {
        }
    }
### 未使用slot批次提交(有可能效率略差于前者)
//获取jedis连接

         private JedisCluster jedisCluster=JedisClusterUtil.getJedisCluster();

         //@param pattern  获取key的前缀  全是是 * 

 public static TreeSet<String> keys(String pattern){  


       TreeSet<String> keys = new TreeSet<>();  
        //获取所有的节点

               Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();  
       //遍历节点 获取所有符合条件的KEY 

               for(String k : clusterNodes.keySet()){  
           logger.debug("Getting keys from: {}", k);  
           JedisPool jp = clusterNodes.get(k);  
           Jedis connection = jp.getResource();  
           try {  
               keys.addAll(connection.keys(pattern));  
           } catch(Exception e){  
               logger.error("Getting keys error: {}", e);  
           } finally{  
               logger.debug("Connection closed.");  
               connection.close();//用完一定要close这个链接!!!  
           }  
       }  
       logger.debug("Keys gotten!");  
       return keys;  
  }  

          //main方法

 public static void main(String[] args ){
 TreeSet<String> keys=keys("*");

 //遍历key  进行删除  可以用多线程

 for(String key:keys){

                          jedisCluster.del(key);
 System.out.println(key);
 }
 }

Reference

[1]. (码经)如何通过正则匹配删除Redis里的键
[2]. (Stackoverflow)Redis/Jedis - Delete by pattern?
[3]. (JavaDoc)Class JedisCluster
[4]. (csdn)redis cluster 模式如何批量删除指定前缀的key
[5]. redis cluster模式key的模糊删除-java操作
[6]. Jedis实现批量删除redis cluster
[6]. redis del命令支持正则删除(pattern)
[7]. Redis 批量删除Redis的key 正则匹配删除
[8]. (名字挺搞笑-蛋糕店老板)Redis集群下使用Jedis实现keys模糊查询

到此这篇关于Redis Cluster 字段模糊匹配及删除的文章就介绍到这了,更多相关Redis Cluster 字段模糊删除内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
浅谈Redis主从复制以及主从复制原理
May 29 Redis
深入理解redis中multi与pipeline
Jun 02 Redis
Redis可视化客户端小结
Jun 10 Redis
了解Redis常见应用场景
Jun 23 Redis
k8s部署redis cluster集群的实现
Jun 24 Redis
解析redis hash应用场景和常用命令
Aug 04 Redis
Jedis操作Redis实现模拟验证码发送功能
Sep 25 Redis
redis中lua脚本使用教程
Nov 01 Redis
浅谈Redis的事件驱动模型
May 30 Redis
Redis实现主从复制方式(Master&Slave)
Jun 21 Redis
一文教你快速生成MySQL数据库关系图
Jun 28 Redis
redis protocol通信协议及使用详解
Jul 15 Redis
redis哨兵常用命令和监控示例详解
May 27 #Redis
Java Socket实现Redis客户端的详细说明
May 26 #Redis
redis实现共同好友的思路详解
详解Redis瘦身指南
May 26 #Redis
Redis高级数据类型Hyperloglog、Bitmap的使用
May 24 #Redis
redis实现排行榜功能
May 24 #Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 #Redis
You might like
深入PHP magic quotes的详解
2013/06/17 PHP
完美解决令人抓狂的zend studio 7代码提示(content Assist)速度慢的问题
2013/06/20 PHP
php随机取mysql记录方法小结
2014/12/27 PHP
10款实用的PHP开源工具
2015/10/23 PHP
java模拟PHP的pack和unpack类
2016/04/13 PHP
Javascript Math对象
2009/08/13 Javascript
jQuery 标题的自动翻转实现代码
2009/10/14 Javascript
JavaScript 利用StringBuffer类提升+=拼接字符串效率
2009/11/24 Javascript
写了10年的Javascript也未必全了解的连续赋值运算
2011/03/25 Javascript
JQuery.closest(),parent(),parents()寻找父结点
2012/02/17 Javascript
jQuery中appendTo()方法用法实例
2015/01/08 Javascript
ECHO.js 纯javascript轻量级延迟加载的实例代码
2016/05/24 Javascript
微信小程序 网络请求(GET请求)详解
2016/11/16 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
Net微信网页开发 使用微信JS-SDK获取当前地理位置过程详解
2019/08/26 Javascript
Python算法之图的遍历
2017/11/16 Python
Python编程使用*解包和itertools.product()求笛卡尔积的方法
2017/12/18 Python
python使用udp实现聊天器功能
2018/12/10 Python
Python解析、提取url关键字的实例详解
2018/12/17 Python
Python迭代器iterator生成器generator使用解析
2019/10/24 Python
django有外键关系的两张表如何相互查找
2020/02/10 Python
Python安装依赖(包)模块方法详解
2020/02/14 Python
python 读取二进制 显示图片案例
2020/04/24 Python
scrapy-redis分布式爬虫的搭建过程(理论篇)
2020/09/29 Python
搭建pypi私有仓库实现过程详解
2020/11/25 Python
使用phonegap进行本地存储的实现方法
2017/03/31 HTML / CSS
Michael Kors加拿大官网:购买设计师手袋、手表、鞋子、服装等
2019/03/16 全球购物
事业单位公务员的职业生涯规划
2014/01/15 职场文书
局火灾防控工作方案
2014/05/25 职场文书
2014市府办领导班子“四风问题”对照检查材料思想汇报
2014/09/24 职场文书
2014年采购部工作总结
2014/11/20 职场文书
地道战观后感300字
2015/06/04 职场文书
导游词之安徽九华山
2019/09/18 职场文书
4种非常实用的python内置数据结构
2021/04/28 Python
WINDOWS下安装mysql 8.x 的方法图文教程
2022/04/19 MySQL