最近项目中需要获取指定前缀的key, 然后删除这些key, 作为对redis命令不太深入了解的我第一想法就是redis的keys命令, 只需keys prefix + * 就可以了, 在测试环境这样开发没有问题, 由于项目对redis依赖比较大, 就网上找了一些关于redis的keys命令, 得知keys命令执行的时候会严重阻塞线上其它命令的正常请求, 于是做了以下替代方案
/**
* 获取指定前缀的一系列key
* 使用scan命令代替keys, Redis是单线程处理,keys命令在KEY数量较多时,
* 操作效率极低【时间复杂度为O(N)】,该命令一旦执行会严重阻塞线上其它命令的正常请求
* @param keyPrefix
* @return
*/
public Set<String> keys(String keyPrefix) {
String realKey = keyPrefix + "*";
try {
return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
Set<String> binaryKeys = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(realKey).count(Integer.MAX_VALUE).build());
while (cursor.hasNext()) {
binaryKeys.add(new String(cursor.next()));
}
return binaryKeys;
});
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
}
return null;
}
/**
* 删除指定前缀的一系列key
* @param keyPrefix
*/
public void removeAll(String keyPrefix) {
try {
Set<String> keys = keys(keyPrefix);
redisTemplate.delete(keys);
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
}
}
经测试, 效果和keys一样