redis-cli --raw keys "prefix-*" | xargs redis-cli del
直接在linux下通过redis的keys命令匹配到所有的key,然后调用系统命令xargs来删除,看似十全十美,实则风险巨大。这就是一颗随时爆炸的炸弹!我们都知道Redis是单线程服务模式,使用命令 keys * 查询key的时候会阻塞正常的业务请求,甚至造成redis宕机,所以肯定不行。因此,我们在生产环境中应当避免使用上边的方法,那使用什么优雅的方法来解决呢?SCAN!
scan cursor [MATCH pattern] [COUNT count]
MATCH: 匹配规则,例如遍历以ops-coffee-开头的所有key可以写成ops-coffee-*,中间包含-coffee-的可以写成*-coffee-*cursor: 游标,
public void testSetDel(Jedis jedis) {
try {
log.info("---------------- Tests begin -----------------");
initRedisData(jedis);
String givenKey = "prefix_*";
delValuesByKeys(givenKey, jedis);
log.info("开始使用 scan 删除数据 ------------ ");
initRedisData(jedis);
this.delSetValues(givenKey, jedis);
Set<String> keys = jedis.keys(givenKey);
log.info("---------------- Tests end ----------------- 是否存在相同前缀的key result = " + !CollectionUtils.isEmpty(keys));
} catch (Exception e) {
log.error(" 删除指定前缀的key对应的键值对 " + e);
} finally {
if (jedis != null) {
jedis.close();
log.info("关闭jedis连接");
}
}
}
/**
* java redis 删除指定前缀的key对应的键值对
* @param givenKey
* @return
*/
public Boolean delSetValues(String givenKey, Jedis jedis) throws Exception {
log.info("开始模糊删除set中的数据,givenKey = " + givenKey);
List<String> keys = getByScan(givenKey, jedis);
log.info("即将删除的key是 " + keys);
String[] array = keys.toArray(new String[0]);
jedis.del(array);
return true;
}
/**
* Jedis 删除指定前缀的key对应的key,使用keys
* @param givenKey
* @return
*/
public Boolean delValuesByKeys(String givenKey, Jedis jedis) throws Exception {
log.info("开始模糊删除set中的数据,givenKey = " + givenKey);
Set<String> keys = jedis.keys(givenKey);
for (String key : keys) {
log.info("当前 key 是 :" + key);
jedis.del(key);
}
return true;
}
private void initRedisData(Jedis jedis) {
jedis.set("prefix_1333", "1");
jedis.set("prefix_2KKKKK", "2");
jedis.set("prefix_3哈哈哈哈哈哈", "777");
}
// 使用 scan
public List<String> getByScan(String key, Jedis jedis) {
List<String> list = new ArrayList<>();
ScanParams params = new ScanParams();
params.match(key);
params.count(100);
String cursor = "0";
while (true) {
ScanResult scanResult = jedis.scan(cursor, params);
List<String> eles = scanResult.getResult();
if (!CollectionUtils.isEmpty(eles)) {
list.addAll(eles);
}
cursor = scanResult.getStringCursor();
if ("0".equals(cursor)) {
break;
}
}
log.info(" getByScan 查到的数据集是 ============ " + list);
return list;
}
测试结果:
---------------- Tests begin -----------------
开始模糊删除set中的数据,givenKey = prefix_*
当前 key 是 :prefix_1333
当前 key 是 :prefix_3哈哈哈哈哈哈
当前 key 是 :prefix_2KKKKK
开始使用 scan 删除数据 ------------
开始模糊删除set中的数据,givenKey = prefix_*
getByScan 查到的数据集是 ============ [prefix_1333, prefix_2KKKKK, prefix_3哈哈哈哈哈哈]
即将删除的key是 [prefix_1333, prefix_2KKKKK, prefix_3哈哈哈哈哈哈]
---------------- Tests end ----------------- 是否存在相同前缀的 key result = false
原文:https://www.cnblogs.com/east7/p/11665392.html