@[TOC](生环境产 redis禁用keys()的解决办法)
/**
* 删除某种格式的key
*
* @param pattern key模式
* @return
* @author huarimin
* @date 2023年8月15日14:43:10
*/
public void delKeyPattern(String pattern) {
// eg pattern="abc*" 模糊匹配所有abc*
RedisConnectionFactory connectionFactory = stringRedisTemplate.getConnectionFactory();
try {
assert connectionFactory != null;
RedisConnection connection = connectionFactory.getConnection();
if (connection instanceof RedisClusterConnection) {
log.info("redis 集群模式 执行集群删除");
delKeyPatternByCluster(pattern);
}else {
log.info("redis 单节点模式 执行单节点删除");
delKeyPatternBySingle(pattern);
}
}catch (Exception e){
log.error("delKeyPattern error", e);
throw e;
}
}
/**
* 描述:删除某种格式的key 单机
*
* @author huarimin
* @date 2023年8月15日14:43:10
*/
private void delKeyPatternBySingle(String pattern) {
Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> stringSet = new HashSet<>();
// 放在try中自动释放cursor
try (Cursor<byte[]> cursor = connection.scan(new ScanOptionsBuilder().match(pattern).count(1000).build())) {
while (cursor.hasNext()) {
stringSet.add(new String(cursor.next()));
}
} catch (IOException e) {
log.error("getTotalKeys cursor close", e);
}
return stringSet;
});
if (!CollectionUtils.isEmpty(keys)) {
stringRedisTemplate.delete(keys);
}
}
/**
* 描述:删除某种格式的key 集群
*
* @author huarimin
* @date 2023年8月15日14:43:10
*/
private void delKeyPatternByCluster(String pattern) {
ArrayList<byte[]> keyList = Lists.newArrayList();
RedisConnectionFactory connectionFactory = stringRedisTemplate.getConnectionFactory();
try {
assert connectionFactory != null;
RedisConnection connection = connectionFactory.getConnection();
if (connection instanceof RedisClusterConnection) {
// 获取RedisAdvancedClusterCommands
LettuceClusterConnection con = (LettuceClusterConnection) stringRedisTemplate.getConnectionFactory().getClusterConnection();
RedisAdvancedClusterAsyncCommands<byte[], byte[]> nativeConnection = (RedisAdvancedClusterAsyncCommands) con.getNativeConnection();
RedisAdvancedClusterCommands<byte[], byte[]> sync = nativeConnection.getStatefulConnection().sync();
// Cursor及pattern设置
KeyScanCursor<byte[]> scanCursor = null;
ScanArgs scanArgs = new ScanArgs();
scanArgs.match(pattern);
do {
if (scanCursor == null) {
scanCursor = sync.scan(scanArgs);
} else {
scanCursor = sync.scan(scanCursor, scanArgs);
}
keyList.addAll(scanCursor.getKeys());
} while (!scanCursor.isFinished());
keyList.forEach(bytes -> stringRedisTemplate.delete(new String(bytes)));
} else {
// 冗余 防止调用出错
log.info("未找到集群配置 执行单节点删除");
delKeyPatternBySingle(pattern);
}
} catch (Exception e) {
log.error("delKeyPatternByCluster error", e);
throw e;
}
}