Redis进阶:管道、事务与发布订阅
Redis进阶:管道、事务与发布订阅摘要: 本篇深入Redis高级操作讲解Pipeline管道批量执行原理与使用、MULTI/EXEC事务配合WATCH实现乐观锁、Pub/Sub发布订阅模式的消息收发实现分享Pipeline中混入耗时操作导致后续命令延迟的踩坑经历对比Pipeline、事务与Lua脚本的适用场景。开篇故事上个月我们做用户积分批量更新1000个用户的积分要同时刷新。同事写了个for循环每个用户一条命令发到Redis。上线后Redis的QPS翻了十倍网络延迟也上去了。我改成Pipeline后1000条命令一次发完执行时间从800ms降到50ms。Redis单线程处理命令但网络往返的延迟可以优化。Pipeline、事务、发布订阅是go-redis的三个进阶能力用好了性能能提升一个量级。这篇我把三者的原理和使用场景讲清楚。一、Pipeline管道批量操作Pipeline把多条命令打包一次网络往返发到Redis结果一次性拿回来。100条命令从100次往返变成1次。packagemainimport(contextfmttimegithub.com/redis/go-redis/v9)// Pipeline基本用法funcpipelineBasic(ctx context.Context,rdb*redis.Client){pipe:rdb.Pipeline()// 注册命令不立即执行返回Cmd用于取结果cmd1:pipe.Set(ctx,key1,value1,0)cmd2:pipe.Get(ctx,key1)// Exec一次性发送所有命令pipe.Exec(ctx)fmt.Println(key1设置结果:,cmd1.Val())fmt.Println(key1的值:,cmd2.Val())}// Pipeline vs 普通操作性能对比funcpipelineBenchmark(ctx context.Context,rdb*redis.Client){constcount1000// 普通方式:逐条执行start:time.Now()fori:0;icount;i{rdb.Set(ctx,fmt.Sprintf(normal:%d,i),x,0)}fmt.Printf(普通方式 %d条: %v\n,count,time.Since(start))// Pipeline方式:批量执行starttime.Now()pipe:rdb.Pipeline()fori:0;icount;i{pipe.Set(ctx,fmt.Sprintf(pipe:%d,i),x,0)}pipe.Exec(ctx)fmt.Printf(Pipeline %d条: %v\n,count,time.Since(start))// Pipeline通常快10-20倍}TxPipeline是事务型Pipeline命令包在MULTI/EXEC里执行保证原子性。// TxPipeline:事务型Pipeline命令要么全成功要么全失败functxPipelineExample(ctx context.Context,rdb*redis.Client){pipe:rdb.TxPipeline()pipe.Incr(ctx,counter)pipe.Set(ctx,flag,done,0)pipe.Expire(ctx,counter,10*time.Minute)pipe.Exec(ctx)}二、事务(MULTI/EXEC/WATCH)Redis事务是一组命令的顺序执行中间不会被其他客户端打断。但Redis事务不支持回滚某条命令出错后面的照样执行。WATCH实现乐观锁的场景很典型。扣库存时先WATCH库存key读取当前值如果大于0就扣减。如果在WATCH和EXEC之间库存被别人改了事务自动失败需要重试。// WATCH实现乐观锁扣库存funcdeductStock(ctx context.Context,rdb*redis.Client,productIDstring)error{stockKey:fmt.Sprintf(stock:%s,productID)maxRetry:3fori:0;imaxRetry;i{// Watch监视stockKey被修改则事务失败err:rdb.Watch(ctx,func(tx*redis.Tx)error{stock,err:tx.Get(ctx,stockKey).Int()iferrredis.Nil{returnfmt.Errorf(商品不存在)}iferr!nil{returnerr}ifstock0{returnfmt.Errorf(库存不足)}// 事务内扣减库存pipe:tx.TxPipeline()pipe.Decr(ctx,stockKey)pipe.HIncrBy(ctx,sales,productID,1)_,errpipe.Exec(ctx)returnerr},stockKey)iferrnil{returnnil// 成功}// 事务冲突则重试iferrredis.TxFailedErr{fmt.Printf(第%d次重试\n,i1)continue}returnerr}returnfmt.Errorf(重试次数用完)}三、发布订阅(Pub/Sub)Pub/Sub是Redis内置的消息广播机制。发布者往channel发消息所有订阅了该channel的客户端都能收到。适合实时通知和聊天室。packagemainimport(contextfmttimegithub.com/redis/go-redis/v9)// 订阅者:监听channelfuncsubscriber(ctx context.Context,rdb*redis.Client,namestring){pubsub:rdb.Subscribe(ctx,chat_room)deferpubsub.Close()// 循环接收消息formsg:rangepubsub.Channel(){fmt.Printf([%s] %s: %s\n,name,msg.Channel,msg.Payload)}}funcmain(){rdb:redis.NewClient(redis.Options{Addr:localhost:6379})deferrdb.Close()ctx:context.Background()// 启动两个订阅者gosubscriber(ctx,rdb,客户端A)gosubscriber(ctx,rdb,客户端B)time.Sleep(time.Second)// 等订阅者就绪// 发布者发消息fori:0;i5;i{rdb.Publish(ctx,chat_room,fmt.Sprintf(消息%d,i1))time.Sleep(time.Second)}time.Sleep(2*time.Second)}Pub/Sub有个特点消息发出去没人订阅就丢了Redis不保存历史消息。需要消息可靠性用Stream或外部消息队列。四、独家踩坑:Pipeline中混入耗时操作这个坑比较隐蔽。我们在一个Pipeline里塞了50条命令其中有一条是KEYS *。结果整个Pipeline的执行时间从20ms飙到3秒后面所有命令都被阻塞了。// 问题代码:Pipeline中混入O(N)耗时命令funcbadPipeline(ctx context.Context,rdb*redis.Client){pipe:rdb.Pipeline()pipe.Set(ctx,k1,v1,0)pipe.Set(ctx,k2,v2,0)// KEYS *是O(N)操作阻塞Redis主线程// Redis单线程执行期间所有后续命令都等着pipe.Keys(ctx,*)pipe.Get(ctx,k1)// 要等KEYS *执行完才能返回pipe.Get(ctx,k2)pipe.Exec(ctx)}排查过程比较曲折。看网络延迟0.3ms正常然后看Redis的SLOWLOG发现KEYS *执行时间有2-3秒。Redis是单线程Pipeline里命令逐条执行一个慢命令阻塞整个Pipeline。修复方案很简单。把KEYS *从Pipeline拿出来单独执行更好的做法是用SCAN替代游标式遍历不阻塞主线程。// 修复后:慢命令独立执行用SCAN替代KEYSfuncfixedPipeline(ctx context.Context,rdb*redis.Client){// Pipeline只放轻量级命令pipe:rdb.Pipeline()pipe.Set(ctx,k1,v1,0)pipe.Set(ctx,k2,v2,0)pipe.Get(ctx,k1)pipe.Get(ctx,k2)pipe.Exec(ctx)// SCAN游标式遍历不阻塞varcursoruint64for{result,newCursor,_:rdb.Scan(ctx,cursor,*,100).Result()fmt.Println(扫描到:,result)cursornewCursorifcursor0{break// 遍历完成}}}经验就是Pipeline里只放O(1)或O(log N)的轻量命令。KEYS、FLUSHALL、大范围SORT这些重操作要独立执行或用SCAN替代。五、对比分析特性Pipeline事务(MULTI/EXEC)Lua脚本原子性无命令间可插入其他客户端命令有顺序执行不被打断有整个脚本原子执行网络往返1次1次1次条件逻辑不支持不支持WATCH只做冲突检测支持脚本内可写if/for错误回滚不涉及不回滚出错继续执行脚本报错不回滚已执行部分适用场景批量读写无依赖需要原子性的简单操作复杂条件判断的原子操作调试难度低中高选择思路很直接。批量读写无依赖用Pipeline。需要原子性但逻辑简单用事务。逻辑复杂且必须原子执行用Lua脚本。日常开发Pipeline用得最多事务次之Lua脚本用在扣库存这类需要条件判断的场景。总结与预告Pipeline是Redis性能优化第一手段把N次网络往返压成1次。事务配合WATCH能实现乐观锁但Redis事务不支持回滚。Pub/Sub适合实时广播不保证消息到达需要可靠消息用Stream。下一篇讲Redis缓存策略深入缓存穿透、击穿、雪崩三种经典问题的解决方案。

相关新闻

AI辅助数学研究实战:Claude与Python生态破解黎曼猜想探索

AI辅助数学研究实战:Claude与Python生态破解黎曼猜想探索

1. 项目概述:当AI“助手”开始挑战数学皇冠最近在AI和数学的交叉圈子里,有个事儿讨论得挺热闹。起因是有开发者声称,利用Claude这个AI模型,在一天半的时间里,对黎曼猜想这个“数学界皇冠上的明珠”取得了某种“新纪录”…

2026/8/18 4:10:18 阅读更多 →
线上问诊AI会误诊、开错药吗?MedGuard声明级风险守门员实测:声明级F1达0.7677、REAL子集精度95.73%,9大基线平均领先21.2%

线上问诊AI会误诊、开错药吗?MedGuard声明级风险守门员实测:声明级F1达0.7677、REAL子集精度95.73%,9大基线平均领先21.2%

一、研究背景 远程医疗在新冠之后飞速普及,互联网医院、AI 问诊助手把"看上病"的地理边界抹平了。但便利的另一面是风险:医生看不见患者的表情、触不到查体,只能依赖屏幕上的文字;家属一句"他状态挺好的"就可…

2026/8/17 3:45:15 阅读更多 →
Redis入门:go-redis基本操作与连接池

Redis入门:go-redis基本操作与连接池

Redis入门:go-redis基本操作与连接池摘要: 本篇讲解Go操作Redis的核心库go-redis v9,包括客户端连接配置、String/Hash/List/Set/ZSet五种数据类型的基本操作、连接池参数调优(PoolSize、MinIdleConns、PoolTimeout),分享连接池耗尽导致请求超时的踩坑经…

2026/8/17 3:45:15 阅读更多 →

最新新闻

20岁的魔兽争霸3,凭什么在现代电脑上跑出144Hz?一份可照抄的优化清单

20岁的魔兽争霸3,凭什么在现代电脑上跑出144Hz?一份可照抄的优化清单

20岁的魔兽争霸3,凭什么在现代电脑上跑出144Hz?一份可照抄的优化清单 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper Warcraft…

2026/8/18 10:07:51 阅读更多 →
浏览器里的图形①:Canvas 最小路径——从画布到第一根线

浏览器里的图形①:Canvas 最小路径——从画布到第一根线

Canvas 是浏览器提供的一块位图画布&#xff1a;你用脚本下指令&#xff0c;像素被画上去&#xff0c;适合图表、小游戏、图像处理入门。 本系列叫「浏览器里的图形」。第一篇只做一件事&#xff1a;从一张空白 <canvas> 走到屏幕上的第一根线。不引入框架&#xff0c;不…

2026/8/18 10:07:51 阅读更多 →
给网页做永久纹身:Highlighter 让每次划重点都不再消失

给网页做永久纹身:Highlighter 让每次划重点都不再消失

给网页做永久纹身&#xff1a;Highlighter 让每次划重点都不再消失 【免费下载链接】highlighter A Chrome extension to highlight text and keep it all saved 项目地址: https://gitcode.com/gh_mirrors/hig/highlighter 深夜十一点&#xff0c;你读完一篇 8000 字的…

2026/8/18 10:07:51 阅读更多 →
告别两小时倒计时:Wand 专业版完整解锁与远程控制实战指南

告别两小时倒计时:Wand 专业版完整解锁与远程控制实战指南

告别两小时倒计时&#xff1a;Wand 专业版完整解锁与远程控制实战指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 聊到"游戏修改工具增强…

2026/8/18 10:07:51 阅读更多 →
Wallpaper Engine 壁纸下载器快速上手指南:3分钟批量下载 Steam 创意工坊动态壁纸

Wallpaper Engine 壁纸下载器快速上手指南:3分钟批量下载 Steam 创意工坊动态壁纸

Wallpaper Engine 壁纸下载器快速上手指南&#xff1a;3分钟批量下载 Steam 创意工坊动态壁纸 【免费下载链接】Wallpaper_Engine 一个便捷的创意工坊下载器 项目地址: https://gitcode.com/gh_mirrors/wa/Wallpaper_Engine Wallpaper Engine 壁纸下载器&#xff08;开源…

2026/8/18 10:07:51 阅读更多 →
大麦抢票自动化实操指南:5分钟上手DamaiHelper,让脚本替你拼手速

大麦抢票自动化实操指南:5分钟上手DamaiHelper,让脚本替你拼手速

大麦抢票自动化实操指南&#xff1a;5分钟上手DamaiHelper&#xff0c;让脚本替你拼手速 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 开售倒计时归零的瞬间&#xff0c;你疯狂刷新页面、狂点按…

2026/8/18 10:06:50 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图&#xff1a;用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手&#xff1a;7个字重免费商用&#xff0c;从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻&#xff1a;设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南&#xff1a;GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者&#xff0c;最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent&#xff0c;从本地部署到云端API&#xff0c;我们正处在一个技术栈快速重构的节点。然而&#xff0c;面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →