记一次redis使用keys
使用场景:项目启动时,索引所有redis缓存删除后重新录入
代码分析:
redisTemplete.keys("*");
优化原因:不能用于生产环境
官方文档描述:
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don’t use KEYS in your regular application code. If you’re looking for a way to find keys in a subset of your keyspace, consider using sets.
原因:
- KEYS命令的性能随着数据库数据的增多而越来越慢
- KEYS命令会引起阻塞,连续的 KEYS命令足以让 Redis 阻塞,尤其是redis存在big value类型数据时
解决方案:使用scan命令
优点:实现同样的功能,不会造成redis阻塞
代码:
/**
* scan 实现
*
* @param pattern 表达式
* @param consumer 对迭代到的key进行操作
*/
public void scan(String pattern, Consumer<byte[]> consumer) {
this.stringRedisTemplate.execute((RedisConnection connection) -> {
try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build())) {
cursor.forEachRemaining(consumer);
return null;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
});
}
/**
* 获取符合条件的key
*
* @param pattern 表达式
* @return
*/
public Set<String> keys(String pattern) {
Set<String> keys = new HashSet<>();
this.scan(pattern, item -> {
//符合条件的key
String key = new String(item, StandardCharsets.UTF_8);
keys.add(key);
});
return keys;
}