结论:首选redisTemplate.executePipelined()配合SessionCallback,每批500–1000条,性能提升8–12倍;它自动复用连接、适配序列化器,避免手动字节操作导致的异常,而RedisCallback需自行处理序列化易出错,且批次过大易OOM、过小则IO节省不明显。

直接上结论:用 redisTemplate.executePipelined() + SessionCallback,控制每批 500–1000 条,性能可提升 8–12 倍;盲目堆高批次或混用 RedisCallback 反而容易触发 OOM 或序列化异常。
为什么 executePipelined(SessionCallback) 是首选
它封装了连接复用和类型安全,自动处理 RedisTemplate 的序列化逻辑(比如你配的 GenericJackson2JsonRedisSerializer),避免手动调 RedisConnection.set() 时裸字节数组导致的乱码或反序列化失败。
-
SessionCallback内部基于RedisOperations,所有opsForValue().set()调用都走你定义好的序列化器,结果也按预期返回 -
RedisCallback直接操作原生RedisConnection,必须自己getBytes()、自己处理 null 和类型,写错一行就ClassCastException - 实测在 10 万条数据导入中,
SessionCallback版本耗时 1.2s,RedisCallback手动序列化版本因 JSON 序列化未对齐多花了 0.4s,且出错后难以定位
批次大小不是越大越好:500–1000 是甜点区间
单次管道打包命令数超过 1000,Redis 服务端响应变慢,客户端内存压力陡增;低于 100 则网络 IO 节省不明显,调度开销占比上升。
- 推荐按
key长度预估:平均 key 长度 - 别硬套“一次塞完”,尤其在容器化环境(如 K8s)下,JVM 堆内临时对象激增可能触发频繁 GC
- 错误示范:
for (i=0; i —— 这会把 10 万条全压进一个 callback,极易 OOM
混合命令与异常处理必须手动兜底
Pipeline 不是事务,某条命令失败(比如 SET key value EX -1 中过期时间非法)不会中断后续执行,但错误信息会被吞掉,只在返回 List 中对应位置为 null 或抛 DataAccessException。
- 务必检查返回值:若用
executePipelined(callback)返回List<object></object>,需遍历确认每项是否为预期类型(如Boolean.TRUE),而非只看 size - 写入场景建议加轻量校验:提前过滤空 key、超长 value(Redis 单 value 限制 512MB,但实际应 ≤ 1MB)、非法过期时间
- 不要依赖 pipeline 自带重试——它不提供重试语义;需外层用
@Retryable或手动分片重推失败子集
真正卡住人的往往不是“怎么发”,而是“发完怎么信”。批量导入时,记得留一手验证手段:比如用 redis-cli --scan --pattern "your:prefix:*" | wc -l 快速核对数量,比等接口日志更可靠。



















