author:徐振东
createTime:2022-05-16
updateTime:2022-06-10
2022-06-10: 培训结束
# Redis批量查询优化
在讲Redis批量查询优化之前,我们先来看一个比较常见的场景,在该场景中,需要在循环体中动态生成key, 然后从redis中获取key的值, 再经过简单的组装后返回给调用者。下面是我们可能采取的代码实现方式:
RedisTemplate<String> redistempalte;
List<String> valueList = new ArrayList<>();
for(int i = 0; i < 10; i++){
String key = "key" + i;
valueList.add(redistempalte.opsForValue().get(key));
}
return valueList;
我们知道,Redis客户端与服务端是通过 Socket
进行通信的,每一次通信都要建立一次Socket
连接,在 redis-server
返回结果后又断开连接。然后在该段代码中, 我们的服务在循环体中与redis-server
进行交互,实际上在底层是进行频繁的创建和销毁Socket
连接,而连接的创建和释放又是非常的耗费系统资源,给系统带来了比较大的负担,严重的话甚至会导致系统停顿,不可访问,无法响应客户端请求,所以我们以后在代码中需要尽量避免在循环体中访问redis。
# 解决方案
# 配置连接池
spring:
redis:
lettuce:
pool:
max-active: 16 # 最大连接数量
max-idle: 8 # 最大空闲连接数量
min-idle: 8 # 最小空闲连接数量
# 使用mGet批量获取数据
RedisTemplate<String> redistempalte;
List<String> keyList = new ArrayList<>();
for(int i = 0; i < 10; i++){
String key = "key" + i;
keyList.add(key);
}
List<String> valueList = redistempalte.opsForValue().multiGet(keyList);
return valueList;
在该段代码中,与第一个版本不同的是,我们在循环体中动态的计算出key后,并不立即与 redis-server
交互,而是将其缓存到一个集合中,在循环结束后再通过mGet命令批量从 Redis 中获取数据,这种方式极大减少了与 Redis
的交互次数,减少 socket
连接的创建与销毁,同时也减少了 IO 次数。所以性能表现要比第一个版本好很多。
# 使用pipeline管道命令
Redis 管道技术可以在服务端未响应时,继续向服务端发送请求,并最终一次性读取所有服务端的响应。
RedisTemplate<String> redistempalte;
List<String> valueList = redistempalte.executePipelined(new SessionCallback<String>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
RedisTemplate<String, Object> strRedisTemplate = (RedisTemplate<String, String>) operations;
for(int i = 0; i < 10; i++){
String key = "key" + i;
strRedisTemplate.opsForValue().get(key);
}
return null;
}
});
return valueList;
← 布隆过滤器 Redis 数据类型 →