首页/新闻资讯/正文详情

Redis 从 0 到 1(十四):接口被刷爆?3 种限流算法的 Go+Redis 实现

发布时间:2026/11/3 22:04:38 来源:云帆数科 栏目:资讯中心
Redis 从 0 到 1(十四):接口被刷爆?3 种限流算法的 Go+Redis 实现
我不会起名字322· 后端 / 算法 / 数据库 技术栈 力扣 Hot100 Go 项目 Redis MySQL文章目录Redis 从 0 到 1十四接口被刷爆3 种限流算法的 GoRedis 实现一、现象秒杀开始 1 秒接口被打爆二、算法 1固定窗口最简单有突刺三、算法 2滑动窗口用 ZSet 精确计数四、算法 3令牌桶平滑限流预支能力五、3 种算法对比与选型收藏点 1六、中间件封装收藏点 2七、命令清单与压测建议八、总结Redis 从 0 到 1十四接口被刷爆3 种限流算法的 GoRedis 实现上一篇《Redis 从 0 到 1十三分布式锁被误删、锁不住Go 无 Lua 实现 3 级防御》我们做出了 redisx.Lock链接https://blog.csdn.net/2501_92769340/article/details/167399708 。本篇把粒度从同一时刻谁能做放宽到单位时间能做多少限流。一、现象秒杀开始 1 秒接口被打爆活动开始瞬间网关日志出现大量 502/超时。Redis 没挂、数据库没挂——是接口的 QPS 超过了它能承受的上限假设单实例只能扛 2000 QPS请求堆积把线程池耗光雪崩开始。限流的目标不是拒绝用户而是在入口就把超出的流量优雅地丢掉返回 429 或降级数据保护系统活到流量峰值过去。3 种经典算法各有坑本篇用 GoRedis 全部实现一遍。二、算法 1固定窗口最简单有突刺// AllowFixedWindow 每 window 秒允许 limit 次funcAllowFixedWindow(ctx context.Context,rdb*redis.Client,keystring,limitint64,window time.Duration)(bool,error){// INCR EXPIRE 的经典组合key 带时间窗口戳天然滚动winKey:fmt.Sprintf(rl:%s:%d,key,time.Now().Unix()/int64(window.Seconds()))pipe:rdb.Pipeline()incr:pipe.Incr(ctx,winKey)pipe.Expire(ctx,winKey,windowtime.Second)// 多留 1 秒防边界误差if_,err:pipe.Exec(ctx);err!nil{returnfalse,err}returnincr.Val()limit,nil}坑在哪窗口边界突刺。限制 100 QPS第 1 秒末尾来了 100 个请求第 2 秒开头又来 100 个——窗口各自都没超限但 2 秒内实际打了 200 QPS服务照样被冲垮。三、算法 2滑动窗口用 ZSet 精确计数思路把每个请求的时间戳存进 ZSetmember唯一 idscore毫秒时间戳每次检查当前时间往前滑一个窗口内的数量。// AllowSlidingWindow 滑动窗口窗口内请求精确计数funcAllowSlidingWindow(ctx context.Context,rdb*redis.Client,keystring,limitint64,window time.Duration)(bool,error){now:time.Now().UnixMilli()winStart:now-window.Milliseconds()zkey:rl:sw:key// 用 WATCH 保证清理旧记录 计数 写入新记录原子第 13 篇的套路varallowedbool_,err:rdb.TxPipelined(ctx,func(pipe redis.Pipeliner)error{pipe.ZRemRangeByScore(ctx,zkey,0,fmt.Sprintf(%d,winStart))// 清掉窗口外的cnt:pipe.ZCard(ctx,zkey)if_,err:pipe.Exec(ctx);err!nil{// 占位go-redis 会在函数返回后统一 EXECreturnerr}allowedcnt.Val()limitifallowed{pipe.ZAdd(ctx,zkey,redis.Z{Score:float64(now),Member:fmt.Sprintf(%d,now)})pipe.Expire(ctx,zkey,windowtime.Second)}returnnil})iferr!nil{// 并发冲突时 WATCH 事务失败直接按拒绝处理限流宁可错杀returnfalse,nil}returnallowed,nil}代价每个请求一条 ZAdd 一条 ZRemRangeByScore 一次事务写放大明显。QPS 高万级时不划算——这时用算法 3。四、算法 3令牌桶平滑限流预支能力令牌桶桶容量burst每秒补充rate个令牌请求拿走一个令牌才放行桶空则拒绝。平滑无突刺且能容忍短时突发。用 Redis Hash 存{tokens, last_refill_time}扣减逻辑用 WATCH/MULTI 保证并发下不多发typeTokenBucketstruct{rdb*redis.Client burstint64ratefloat64// 每秒补充的令牌数}func(b*TokenBucket)Allow(ctx context.Context,keystring)(bool,error){hkey:rl:tb:keyvarallowedbool_,err:b.rdb.TxPipelined(ctx,func(pipe redis.Pipeliner)error{hm:pipe.HGetAll(ctx,hkey)if_,err:pipe.Exec(ctx);err!nil{returnerr}vals:hm.Val()tokens:b.burst last:time.Now().UnixMilli()ift,ok:vals[tokens];ok{fmt.Sscanf(t,%d,tokens)fmt.Sscanf(vals[ts],%d,last)}// 按流逝时间补充令牌上限 burstrefill:float64(time.Now().UnixMilli()-last)/1000*b.rate tokensint64(math.Min(float64(tokens)refill,float64(b.burst)))iftokens0{allowedtruetokens--}pipe.HSet(ctx,hkey,tokens,tokens,ts,time.Now().UnixMilli())pipe.Expire(ctx,hkey,time.Hour)returnnil})iferr!nil{returnfalse,nil}returnallowed,nil}五、3 种算法对比与选型收藏点 1维度固定窗口滑动窗口令牌桶实现复杂度2 条命令ZSet 事务Hash 事务突刺问题窗口边界双倍流量无无突发被 burst 平滑限制写放大低高每请求 3 写中适合场景粗粒度保护如 1 分钟 1000 次精度要求高的计数平滑 QPS 容忍突发API 网关组合用法是生产常态外层固定窗口挡风暴便宜内层令牌桶平滑精确。六、中间件封装收藏点 2funcRateLimitMiddleware(rdb*redis.Client,tb*TokenBucket)func(http.Handler)http.Handler{returnfunc(next http.Handler)http.Handler{returnhttp.HandlerFunc(func(w http.ResponseWriter,r*http.Request){// 按用户/IP 维度限流key 取登录用户 id 或 X-Forwarded-Forkey:r.Header.Get(X-Forwarded-For)ok,err:tb.Allow(r.Context(),key)iferr!nil||!ok{w.Header().Set(Retry-After,1)http.Error(w,{code:429,msg:请求过于频繁},http.StatusTooManyRequests)return}next.ServeHTTP(w,r)})}}配套约定返回 429 要带Retry-After限流维度选谁要想清楚——按 IP 会误伤 NAT 后的公司出口按用户 id 会被小号绕过。七、命令清单与压测建议命令用于算法INCR EXPIRE固定窗口ZADD/ZCARD/ZREMRANGEBYSCORE/ZREVRANGE滑动窗口HGETALL/HSET WATCH/MULTI令牌桶EXPIRE三种都要计数器 key 必须带 TTL否则内存泄漏压测建议用第 5 篇的压测器改造验证100 QPS 限制下压 500 QPS1 秒吞吐 ≈100拒绝率 ≈80%边界测试用固定窗口故意在窗口边界打双倍流量验证滑动窗口/令牌桶确实无突刺。八、总结固定窗口最简单但有边界突刺滑动窗口精确但写放大令牌桶平滑且容忍突发生产组合外层固定窗口挡风暴 内层令牌桶平滑计数器 key 必带 TTL否则限流器自己成为内存泄漏源事务冲突时宁可错杀拒绝不可错放。下一篇预告流量管住了下一篇做一个高频业务——下一篇《千万玩家积分榜——ZSet 排行榜的 Go 实现 5 细节》我们处理同分排序、分页、我的排名这些最容易踩坑的细节。

相关推荐

iloader 如何补齐 iOS 侧载能力缺口:对照 Sideloadly 的源码级差距审计
iloader 如何补齐 iOS 侧载能力缺口:对照 Sideloadly 的源码级差距审计

iloader 如何补齐 iOS 侧载能力缺口:对照 Sideloadly 的源码级差距审计 【免费下载链接】iloader User friendly sideloader 项目地址: https://gitcode.com/GitHub_Trending/iloa/iloader iloader 是跨平台 Tauri 侧载工具。本差距审计以 Sideloadly 为标杆… · 2026/11/3 23:28:54

LunaTranslator:把日文视觉小说实时译成中文,HOOK 提文本 + OCR 补位,3 步跑通
LunaTranslator:把日文视觉小说实时译成中文,HOOK 提文本 + OCR 补位,3 步跑通

LunaTranslator:把日文视觉小说实时译成中文,HOOK 提文本 OCR 补位,3 步跑通 【免费下载链接】LunaTranslator 视觉小说翻译器 / Visual Novel Translator 项目地址: https://gitcode.com/GitHub_Trending/lu/LunaTranslator LunaTra… · 2026/11/3 18:48:41

10-JDK 24 到 27 新特性全解:启动提速、后量子加密与「默认即更快」
10-JDK 24 到 27 新特性全解:启动提速、后量子加密与「默认即更快」

这一篇把 24、25、26、27 四版的关键特性一次讲清,并给出「你现在该用哪个版本」的明确建议。一、先看清三个版本的定位版本GA 时间是否 LTSJEP 数主题JDK 242025-03-18否(已 EOL)24转正 Stream Gatherers / Class-File API,虚拟线… · 2026/11/3 19:56:49

机器学习三大分支:监督学习、无监督学习与强化学习实战解析
机器学习三大分支:监督学习、无监督学习与强化学习实战解析

1. 机器学习领域全景概览第一次接触机器学习时,我被各种术语搞得晕头转向——监督学习、无监督学习、强化学习,这些概念就像迷宫里的岔路。直到在电商平台做了三年的推荐系统开发后,我才真正理解这三个核心分支就像厨师做菜的不同方式&#x… · 2026/11/4 3:22:24

考研小程序开发:SpringBoot与MySQL架构实践
考研小程序开发:SpringBoot与MySQL架构实践

1. 项目背景与需求分析考研备考过程中,资料获取一直是困扰考生的核心痛点。作为一名经历过考研的开发者,我深刻体会到传统资料获取方式的诸多不便:学校官网信息分散、培训机构资料价格昂贵、论坛资源质量参差不齐。这些问题直接影响了备考效率… · 2026/11/4 3:22:24

网页批量转PDF工具:离线渲染、免浏览器、精准分页
网页批量转PDF工具:离线渲染、免浏览器、精准分页

简介:这是一款专为办公、教学及资料整理人员设计的绿色免安装网页批量打印工具,解决逐页打开网页手动打印效率低、易出错的痛点。用户可一次性导入多个HTML文件,一键完成批量打印任务,显著提升报告汇编、课件制作、档案归档等场景… · 2026/11/4 3:22:24

可解释性异常检测技术在工业场景的实践与优化
可解释性异常检测技术在工业场景的实践与优化

1. 项目背景与核心挑战大数据时代的异常检测技术已经成为金融风控、工业质检、网络安全等领域的标配工具。但当我们把深度学习模型部署到生产环境时,经常遇到这样的困境:算法工程师看着99%的准确率报表沾沾自喜,业务部门却对着报警列表一头雾… · 2026/11/4 3:22:24

程序员如何转型架构师:思维跃升与技术突破
程序员如何转型架构师:思维跃升与技术突破

1. 程序员职业转型的必然性十年前我刚入行时,程序员的工作模式确实像"搬砖"——每天重复着CRUD(增删改查)的业务代码编写,调试着相似的业务逻辑,解决着雷同的线上问题。这种状态持续了三年后,我突… · 2026/11/4 3:22:24

解决Cursor编辑器Prettier格式化失效的排查指南
解决Cursor编辑器Prettier格式化失效的排查指南

1. 问题现象与初步排查最近在项目开发中遇到一个棘手问题:Cursor编辑器内置的Prettier代码格式化功能突然失效,状态栏持续显示"Prettier未激活"提示。作为深度依赖自动化格式化的开发者,这种工具链断裂直接影响了编码效率。经过系统… · 2026/11/4 3:21:23

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码