executePipelined是最稳妥的批量pipeline方式,自动管理连接与结果聚合;必须用RedisCallback+RedisConnection调用原生命令,返回List按序对应命令结果。

Spring Data Redis 的 executePipelined 怎么用
直接结论:用 executePipelined 是 Spring 中最稳妥的批量 pipeline 方式,它自动管理连接、命令缓冲和结果聚合,比手动拿 RedisConnection 更安全。
常见错误是试图在 executePipelined 里调用 set、get 这类模板方法——这些方法走的是普通命令通道,不会进 pipeline。必须用 RedisCallback + RedisConnection 原生命令。
- 只接受一个
RedisCallback参数,回调里通过connection调用set、mSet、hMGet等底层方法 - 返回值是
List<object></object>,顺序严格对应你发命令的顺序,null 表示该命令无返回(比如set) - 不要在回调里做耗时操作或抛异常,否则 pipeline 会中断,已发命令仍可能执行成功
redisTemplate.executePipelined((RedisConnection connection) -> {
connection.set("k1".getBytes(), "v1".getBytes());
connection.mSet(new byte[][]{
"k2".getBytes(), "v2".getBytes(),
"k3".getBytes(), "v3".getBytes()
});
connection.hMGet("hash1".getBytes(), new byte[][]{"f1".getBytes(), "f2".getBytes()});
return null; // 忽略返回,结果由 executePipelined 自动收集
});
为什么不用 RedisTemplate.opsForXxx().multi()
因为 multi() 开启的是 Redis 的事务(MULTI/EXEC),不是 pipeline。它加了 WATCH 和原子性保证,但吞吐反而更低,且不解决网络往返问题。
真实场景中,95% 的“批量写”需求其实只要 pipeline:减少 RTT、提升吞吐,不需要事务隔离。用 multi() 不仅没收益,还容易误以为自己实现了原子写入——实际只是把多个命令打包发过去,失败时部分成功部分失败。
-
multi()+exec()返回的是List<object></object>,但语义是事务结果,不是 pipeline 响应 - 事务模式下,如果中间某条命令语法错误,
EXEC仍会执行前面成功的命令(Redis 4.0+ 才支持 EXEC 失败回滚) - Pipeline 没有事务开销,也不阻塞其他客户端,适合日志打点、缓存预热等高吞吐场景
executePipelined 的返回结果怎么解析
返回的 List<object></object> 是 raw response,类型取决于你发的每条命令:比如 set 返回 null,get 返回 byte[],hMGet 返回 List<byte></byte>。Spring 不做自动反序列化。
最容易踩的坑是假设所有结果都是字符串或都可转成 String——实际得按命令顺序逐个判断类型,尤其混用不同命令时。
- 用
Objects.toString(result, null)安全转换,避免 NPE - 对
hMGet、mGet这类批量读命令,结果本身是嵌套结构,需二次遍历 - 如果用了自定义
RedisSerializer(如GenericJackson2JsonRedisSerializer),raw bytes 需手动解码,pipeline 不走模板的序列化逻辑
Pipeline 在连接池和超时配置上要注意什么
pipeline 本身不改变连接生命周期,但它会让单次连接占用时间变长——所有命令串行发、串行收,所以连接池配置不当会导致阻塞。
默认 LettucePoolingClientConfiguration 的 maxIdle 和 minIdle 如果太小,高并发 pipeline 请求会排队等连接;而 timeout 如果设得太短,大 pipeline 可能被误判为超时断连。
- 建议把
maxWaitTimeout(Lettuce)或max-wait(Jedis)设为 3–5 秒,避免 pipeline 卡住整个池 - 单次 pipeline 命令数控制在 100–500 条以内,太多会导致响应延迟不可控,也增加 OOM 风险
- 别在 pipeline 回调里调用外部服务或 DB,这会让连接空转,浪费池资源
真正难处理的是 pipeline 中某条命令失败(比如 key 过期、类型错)——Redis 不会中断后续命令,但你的业务逻辑可能依赖前序结果。这种耦合得靠代码分段或重试策略兜底,框架不管。

















