rediscluster全局数据_Redis & Redis Cluster 字段模糊匹配及删除

在Redis中,可以使用keys或scan命令进行模糊匹配,但Redis Cluster不支持keys命令。在单节点,可通过Jedis的keys或scan方法配合删除操作。在集群环境中,由于数据分布,需要采用不同策略,如使用Hash-Tag或遍历各节点的scan。本文探讨了针对Redis Cluster的键的模糊匹配和删除方法。
摘要由CSDN通过智能技术生成

Questions

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

单节点的情况

Jedis

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

### 方法1

Set 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 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 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 clusterNodes = jedisCluster.getClusterNodes();

for (Map.Entry entry : clusterNodes.entrySet()) {

Jedis jedis = entry.getValue().getResource();

// 判断非从节点(因为若主从复制,从节点会跟随主节点的变化而变化)

if (!jedis.info("replication").contains("role:slave")) {

Set keys = jedis.keys(redisKeyStartWith + "*");

if (keys.size() > 0) {

Map> 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> 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();

[email protected] pattern 获取key的前缀 全是是 *

public static TreeSet keys(String pattern){

TreeSet keys = new TreeSet<>();

//获取所有的节点

Map 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 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模糊查询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值