redis pipeline性能优化操作
redis pipeline—批量设置缓存
// 使用StringRedisTemplate执行Redis操作回调,此处目的是批量更新Redis中的数据
stringRedisTemplate.execute((RedisCallback<Object>) e -> {
// 开启Redis Pipeline,Pipeline允许你在一次服务器往返行程中发送多条命令,
// 并且服务器将会序列化执行这些命令,最后将结果打包返回,极大地减少了网络IO开销
e.openPipeline();
// 遍历之前准备好的待更新数据映射(newMap),其中key是要更新的Redis键,value是包含待存储值和过期时间的JSONObject
newMap.forEach((key, value) -> {
// 从value JSONObject中获取过期时间(单位可能为秒),如果不存在则默认为null
Long expireTime = value.getLong("expireTime");
// 根据expireTime是否存在选择不同的Redis命令
if (expireTime == null) {
// 如果没有指定过期时间,则使用set命令直接设置键值对
e.set(key.getBytes(StandardCharsets.UTF_8), // 将键转换为字节数组
value.getString("pos_status").getBytes(StandardCharsets.UTF_8)); // 将值(pos_status字段)转换为字节数组
} else {
// 如果指定了过期时间,则使用setEx命令设置键值对及过期时间(单位转换为秒)
e.setEx(key.getBytes(StandardCharsets.UTF_8), // 键转换为字节数组
value.getLong("expireTime"), // 直接使用过期时间,无需转换,因为setEx接收long型参数
value.getString("pos_status").getBytes(StandardCharsets.UTF_8)); // 值转换为字节数组
}
});
// 结束Pipeline操作,所有之前的命令将被序列化执行
e.closePipeline();
// RedisCallback要求返回一个Object,这里操作完成无需返回具体结果,故返回null
return null;
});
redis pipeline—批量获取缓存
public void batchListDeviceAttrVersion(List<DevicePOJO> devices) {
List<Object> deviceAttrs = redisTemplate.executePipelined(new RedisCallback<DevicePOJO>() {
@Nullable
@Override
public DevicePOJO doInRedis(@NotNull RedisConnection connection) throws DataAccessException {
connection.openPipeline();
for (DevicePOJO device : devices) {
connection.hGetAll((CacheConstant.DEVICE_ATTR_VERSION + device.getDeviceId()).getBytes());
}
return null;
}
}, redisTemplate.getValueSerializer());
List<DevicePOJO> needQueryDb = new ArrayList<>();
for (int i = 0; i < devices.size(); i++) {
DevicePOJO device = devices.get(i);
Object deviceAttr = deviceAttrs.get(i);
if (deviceAttr == null || JSONObject.parseObject(JSON.toJSONString(deviceAttr)).size() == 0) {
needQueryDb.add(device);
continue;
}
}
}