news 2026/7/17 14:52:41

Redis 性能优化实战:Pipeline 和 multiGet

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis 性能优化实战:Pipeline 和 multiGet

Redis 性能优化实战:Pipeline 和 multiGet

循环里调redisTemplate.opsForValue().get(key)——每次都是独立的一次网络往返。100 个 key 就是 100 次网络 IO,99 次纯浪费在 TCP 握手和等待上。Redis 自己一毫秒就查完了,但你花了 100 毫秒在路上。Pipeline 把一堆命令打包发过去一口气执行,multiGet 把多个 GET 合并成一条命令——两种手段,干的同一件事:砍掉多余的往返。


没有 Pipeline 的时候,循环 GET 有多慢

// 经典反例:循环 GET——100 个 key = 100 次 Redis 请求for(Stringkey:keys){Stringvalue=redisTemplate.opsForValue().get(key);// 每次都是独立的网络往返// ...}
RedisJavaRedisJava... 100 次往返 ...GET user:1value1GET user:2value2GET user:3value3GET user:100value100

Redis 单线程,执行一次 GET 不到 1ms。但网络往返每次 1ms,100 个 key 累计 100ms。耗时不在 Redis 身上——全花在来回的网络上。


方案一:multiGet——合并成一条命令,一次往返查完

multiGet把多个 GET 合并成一条 Redis 命令MGET,一次网络往返拿回所有结果。

RedisJavaRedisJava一口气查完 100 个 keyMGET user:1 user:2 user:3 ... user:100[value1, value2, value3, ..., value100]

从 100 次往返变成 1 次。耗时从 100ms 降到 ~2ms。

代码

// 构建 Redis Key 列表List<String>redisKeys=userIds.stream().map(RedisKeyConstants::buildUserInfoKey).toList();// 一次 multiGet,查完所有 keyList<Object>redisValues=redisTemplate.opsForValue().multiGet(redisKeys);// 过滤掉不存在的 key(值为 null)redisValues=redisValues.stream().filter(Objects::nonNull).toList();

实战常用:批量查完,缺的再走数据库

不是所有 key 都命中了缓存,对没命中的部分降级查 DB:

// 先从 Redis 批量查List<Object>redisValues=redisTemplate.opsForValue().multiGet(redisKeys);// 把命中的转成结果集List<UserVO>result=redisValues.stream().filter(Objects::nonNull).map(v->JsonUtils.parseObject(v.toString(),UserVO.class)).toList();// 全命中了——直接返回if(result.size()==userIds.size()){returnresult;}// 没全命中——找出缺失的 userId,查 DBList<Long>missedIds=userIds.stream().filter(id->result.stream().noneMatch(u->u.getId().equals(id))).toList();List<UserVO>dbResults=userMapper.selectByIds(missedIds);result.addAll(dbResults);// 异步把 DB 查到的回种到 RedisthreadPool.submit(()->{for(UserVOuser:dbResults){Stringkey=buildUserInfoKey(user.getId());longexpire=24*3600+ThreadLocalRandom.current().nextInt(24*3600);redisTemplate.opsForValue().set(key,JsonUtils.toJsonString(user),expire,TimeUnit.SECONDS);}});returnresult;

关键点:过期时间加了随机值。如果不加随机值,100 个 key 都在同一秒过期,下一秒全打在 DB 上——这就是缓存雪崩。


方案二:Pipeline——多条不同类型的命令打包一起执行

multiGet只能干一件事:批量 GET。如果你需要混合操作——比如批量 SET 100 个不同 value,或者 SET + EXPIRE 一起,multiGet 就管不了了。

Pipeline 不限制命令类型:你可以把任意数量的 GET、SET、DEL、EXPIRE……打包成一个批次,一次网络往返发给 Redis。

RedisJavaRedisJava一口气执行完 100 条命令SET user:1 {json1} EX 86400SET user:2 {json2} EX 86400SET user:3 {json3} EX 86400...SET user:100 {json100} EX 86400[OK, OK, OK, ..., OK]

代码

// 异步线程将用户信息批量同步到 Redis 中threadPoolTaskExecutor.submit(()->{Map<Long,UserVO>map=dbResults.stream().collect(Collectors.toMap(UserVO::getId,u->u));// 执行 Pipeline——一批 SET 命令打包发送redisTemplate.executePipelined(newSessionCallback<>(){@OverridepublicObjectexecute(RedisOperationsoperations){for(UserDOuser:userList){Stringkey=RedisKeyConstants.buildUserInfoKey(user.getId());Stringvalue=JsonUtils.toJsonString(map.get(user.getId()));longexpire=24*3600+RandomUtil.randomInt(24*3600);// 这里的 SET 不会立刻发到 Redis——攒在 Pipeline 里operations.opsForValue().set(key,value,expire,TimeUnit.SECONDS);}returnnull;// Pipeline 里的返回值不关心}});});

关键细节

Pipeline 里的命令不会立即发送。executePipelined里所有的operations.xxx()调用只是把命令加入缓冲区,execute方法结束后,这批命令一次性发给 Redis。

Pipeline 不保证原子性。跟 Lua 脚本不一样——Pipeline 只是"打包发送",Redis 接收后逐条执行,中间可能被其他客户端插一条命令。需要原子性还是得用 Lua。

返回值为 null。Pipeline 模式下每条命令的结果可以不收集(return null),因为我们只关心"写进去没有",不关心返回值。如果想知道每一条的执行结果,可以收集但不常用。


三种方式对比

循环 GETmultiGetPipeline
网络往返N 次(N = key 数量)1 次1 次
支持的操作所有类型仅 GET(MGET)所有类型(GET/SET/DEL/EXPIRE……)
原子性单条 GET 原子不保证不保证
适用场景查 1~2 个 key只读,批量查多个 key读写混合,批量操作

日常使用:查多用 multiGet,写多用 Pipeline。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/17 14:51:30

XbsjEarthUI性能优化:大规模POI加载与渲染优化技巧

XbsjEarthUI性能优化&#xff1a;大规模POI加载与渲染优化技巧 【免费下载链接】XbsjEarthUI XbsjEarthUI是基于Cesium和EarthSDK的三维GIS/BIM的UI模板&#xff0c;可以基于此定制自己的三维App 项目地址: https://gitcode.com/gh_mirrors/xb/XbsjEarthUI XbsjEarthUI是…

作者头像 李华
网站建设 2026/7/17 14:48:43

替换BI最容易踩的5个坑:从数据孤岛到二次孤岛

导语 先澄清一个容易被混用的概念&#xff1a;"数据孤岛"和"二次孤岛"不是一回事。前者是很多企业启动BI项目时最初想解决的问题——数据散落在ERP、CRM、WMS、财务系统里&#xff0c;口径各异、无法联动分析&#xff1b;而"二次孤岛"&#xff0…

作者头像 李华
网站建设 2026/7/17 14:46:48

45.7MB 轻量部署包,OpenClaw 2.7.9 Windows 一键部署全流程

核心亮点&#xff1a;提供全程可视化图形操作界面&#xff0c;自动补齐全套运行依赖&#xff0c;数据独立存储于本地设备&#xff0c;兼容多款主流大模型&#xff0c;并采用轻量化的 45.7MB 整合压缩包。 教程适配&#xff1a;OpenClaw | 适配 Windows10/11、macOS 双系统 &…

作者头像 李华
网站建设 2026/7/17 14:46:44

终极米哈游扫码登录助手:一键快速登录四大热门游戏

终极米哈游扫码登录助手&#xff1a;一键快速登录四大热门游戏 【免费下载链接】MHY_Scanner MHY扫码登录器&#xff0c;支持从直播流抢码。 项目地址: https://gitcode.com/gh_mirrors/mh/MHY_Scanner MHY_Scanner是一款专为米哈游玩家设计的开源扫码登录工具&#xff…

作者头像 李华
网站建设 2026/7/17 14:46:40

3分钟快速上手dedao-dl:从命令行小白到下载高手

3分钟快速上手dedao-dl&#xff1a;从命令行小白到下载高手 【免费下载链接】dedao-dl 得到 APP 课程下载工具&#xff0c;可在终端查看文章内容&#xff0c;可生成 PDF&#xff0c;音频文件&#xff0c;markdown 文稿&#xff0c;可下载电子书。可结合 openclaw skill 等使用 …

作者头像 李华