Spring Data Redis与Lettuce 使用 pipeline 时注意事项
Contents
起因
在优化线上系统代码时, 通过抓包发现当 Spring 中的 RedisTemplate 底层使用 Lettuce 库时, 并不是真正的 pipeline .
代码如下
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("10.0.0.40", 6479);
config.setPassword("pwd");
LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
return factory;
}
// 调用代码:
redisTemplate.executePipelined((RedisCallback<Object>) redisConnection -> {
redisConnection.hSet("hell1".getBytes(), "hash1".getBytes(), "hellovalue1".getBytes());
redisConnection.hSet("hell2".getBytes(), "hash2".getBytes(), "hellovalue2".getBytes());
redisConnection.hSet("hell3".getBytes(), "hash3".getBytes(), "hellovalue3".getBytes());
redisConnection.hSet("hell4".getBytes(), "hash4".getBytes(), "hellovalue4".getBytes());
return null;
});
使用 tcpdump 抓包发现如下:
真正的 pipeline 请求是像下面这样子的:
注意, 其实 Lettuce 的行为很奇怪. 在 Spring RedisTemplate 中的 executePipelined 方法中的情况:
- 有时完全是一条一条命令地发送
- 有时全合并几条命令发送
- 但跟完全 pipeline 的方式不同, 测试多次, 但没发现有一次是完整 pipeline 的
解法方法
目前使用 Spring RedisTemplate 中的 executePipelined 中对 Lettuce 未真正支持 pipeline. 所以这点要特别注意.
- 切换为 Jedis 库. Spring 对 Jedis 库的 pipeline 支持正常
- Lettuce 中的话, 只好手工写代码来使用 pipeline 了. 参考官方文档 Lettuce.io
- 代码中, 记得要复用
ClientResources
对象. 它类似 Netty 中的EventLoopGroup 配置.
- 代码中, 记得要复用
Jedis 与 Lettuce 对比
参考