mget 比多次 get 快因减少网络往返(rtt),一次请求批量获取多个键;但单次不宜超 100 个 key,推荐 32~64 个分片调用,注意类型匹配、序列化配置及大 key 风险。

为什么 MGET 比多次 GET 快
因为每次 GET 都要走一次网络往返(RTT),而 MGET 把多个键打包进一个请求,服务端原子执行、一次返回。在跨机房或高延迟网络下,省下的 RTT 就是实打实的毫秒级收益。但要注意:这不是“越大批量越好”,Redis 处理大请求本身有开销,且客户端和网络层对单包大小有限制。
Spring Boot 中用 RedisTemplate 调用 MGET 的正确姿势
RedisTemplate 本身不直接暴露 mget 方法,得用 execute + RedisCallback 或升级到 Lettuce 原生支持。常见错误是手动循环 opsForValue().get(key),这完全失去批量意义。
- 推荐用
StringRedisTemplate的opsForValue().multiGet(keys)—— 它底层就是调MGET,且自动处理null转换 - 传入的
keys是List<string></string>,不能为null,空集合会返回空列表,不会报错 - 如果 keys 里含不存在的 key,对应位置返回
null,不是抛异常,业务需判空 - 避免把上万 keys 一次性塞进去;测试表明超过 100 个 key 后,单次
MGET性能衰减明显(降到单 key 的 40% 左右)
MGET 的性能拐点在哪?怎么分片
实测数据很关键:MGET 在 10 个 key 以内几乎线性高效;到 50 个时性能约降为单 key 的 60%;超 100 个后吞吐下降陡峭,且易触发 Redis 的 client-output-buffer-limit 限制或客户端 OOM。
- 建议单次
MGET控制在 32~64 个 key 之间,这是多数生产环境的平衡点 - 若需查 500 个 key,拆成 8–16 批异步并发调用(用
CompletableFuture),比单批更稳 - 别用
pipeline包裹多个GET来模拟MGET—— 它不等价:MGET是服务端原子批量读,pipeline只是减少 RTT,仍可能被其他命令穿插执行 - 注意 Spring Boot 默认的
StringRedisTemplate序列化器是JdkSerializationRedisSerializer,会导致 value 被序列化成二进制,multiGet返回的是字节数组而非字符串;务必确认已配置StringRedisTemplate使用StringRedisSerializer
容易被忽略的 Nil 和类型陷阱
MGET 返回的 List 里,缺失 key 对应位置是 null,不是空字符串,也不是 "nil"。但如果你用的是 HashOperations 或 BoundValueOperations,误调了 hmget 或 get,结果就完全不对。
- 确认你操作的是 String 类型数据;若 key 实际存的是 Hash、List 或 JSON 字符串,
MGET只能取整个 value,无法按字段拆解 - Spring Boot 的
multiGet返回List<string></string>,但若原始 value 是 JSON,你需要自己反序列化;别指望框架自动做 - 如果某 key 是通过
SET key "value" EX 60写入,而另一些是HSET hashkey f1 v1,混在一起用MGET查,后者会返回null(因为MGET查不到 Hash 结构的 field) - Redis 服务端返回的
(nil)在 Java 层就是null,别用.equals("null")判空
MGET —— 单次响应体膨胀,网络卡顿,GC 压力陡增。先用 redis-cli --bigkeys 扫一遍,再决定要不要拆结构或改用 Hash 分字段存。











