刚上线的活动接口,被一波 "羊毛党"+ 真实用户的流量直接干到 503,老板在群里连环 @,运维催着查日志,我盯着监控里的 "请求峰值",手都在抖 ------ 后来才发现,不是代码写得烂,是没给系统装个 "流量刹车":Sentinel 的限流算法!
今天咱不整晦涩的公式,用大白话把 Sentinel 里最常用的 4 种限流算法扒明白,从 "小白能懂" 到 "落地能用",让你下次再遇高并发,腰板都能挺得更直~
先唠唠:为啥需要限流算法?------ 后端 er 的 "保命刚需"
简单说,限流就是 "掐流量":当请求多到系统扛不住时,按规矩拦一部分,保证剩下的请求能正常处理,避免系统直接 "躺平"。
就像奶茶店排队,要是一下子来 100 个人,店员忙不过来会乱套;但如果说 "一次只接待 20 人,剩下的排队",虽然有人等,但店里能正常出单 ------ 限流算法就是奶茶店的 "排队规则",而 Sentinel 就是那个 "维持秩序的店员"。
1. 简单计数器:最 "直男" 的限流,固定时间里 "卡数量"
这是限流界的 "入门款",也叫 "固定时间窗口",逻辑简单到离谱,跟小区快递柜似的:"下午 2 点 - 3 点,最多放 100 个快递,超了就不让放"。
咋操作?
- 定俩规矩:① 时间窗口(比如 1 分钟);② 窗口内最大请求数(比如 100 次);
- 来了请求就给计数器 + 1,看有没有超 100 次:没超就放行,超了就拦截;
- 等 1 分钟一到,计数器直接清零,重新开始算。
优点:简单到 "不用带脑子"
新手也能 10 分钟上手,不管是写代码还是调参数,都没门槛 ------ 适合非核心接口(比如 "用户反馈" 接口),偶尔超一点也不影响。
坑点:致命的 "临界问题"!
这是我踩过的大坑!举个例子:例如限流每秒5个 第1秒的前0.8秒里一次请求都没有;后0.2秒有5次请求 第2秒的前0.2秒有5次请求;后0.8秒一次请求都没有 最终:上一秒的后0.2秒~下一秒的前0.2秒 期间,请求量为10,超出限流阈值,可能导致服务阻塞或宕机。
就像快递柜下午 2 点 - 3 点限 100 个,结果 2:59 放 99 个,3:00 又放 99 个,1 分钟挤了 198 个,柜子直接爆了...
2. 滑动时间窗口:给 "直男" 装 "细粒度滤镜",解决临界问题
既然简单计数器会 "翻车",那咱就把大窗口切成小格子 ------ 滑动时间窗口,相当于给限流加了个 "放大镜",精度直接拉满。
咋操作?
- 把 1 分钟的大窗口,切成 60 个 1 秒的小窗口(每个小窗口有自己的计数器);
- 来了请求,只给当前时间的小窗口 + 1;
- 算限流时,不看整个大窗口,而是看 "当前时间往前推 1 分钟" 的所有小窗口总和;
- 时间一滑,老的小窗口(超过 1 分钟的)就 "过期作废",只算新的。
比如还是 1 分钟限 100 次:第 59 秒来 99 次(小窗口 59=99),第 60 秒来 1 次(小窗口 60=1),总和 100;第 61 秒再来 1 次,计算范围变成第 2-61 秒,总和 99+1+1=101,直接拦截 ------ 临界问题解决!
优点:精度高,流量更稳
核心接口用它不慌,再也不怕 "瞬间超流",比如 "订单创建" 接口,用这个能避免订单量突增导致数据库崩。
坑点:费资源!
要维护 60 个小窗口的计数器,每次还要把范围内的小窗口加起来算 ------ 小窗口分越细,精度越高,但内存和计算开销也越大,系统自己可能先累着。
3. 漏桶算法:像家里的漏斗,再猛的流量也 "捋顺了"
前面俩都是 "按时间算数量",漏桶算法不一样,它是 "按速度算"------ 就像家里的漏斗,不管你倒多快的水,下面漏出来的速度永远固定,水满了就溢出来。
咋操作?
- 有个 "漏桶":① 容量(最多装多少水);② 漏出速率(每秒漏多少水);
- 来了请求 = 往桶里倒水:桶没满就倒,满了就泼掉(拦截);
- 漏桶按固定速率 "漏水",漏一勺水 = 处理一个请求。
优点:流量绝对平稳!
不管外面请求多疯,系统处理速度始终不变 ------ 特别适合下游是 "慢服务" 的场景,比如数据库写入:数据库每秒只能处理 10 次写入,用漏桶把请求速率掐在 10 次 / 秒,数据库就不会崩。
坑点:太死板,浪费资源!
比如漏桶每秒漏 10 次,某秒只来 5 次请求,桶里空了 5 个位置,但它还是按 10 次 / 秒漏;下一秒来 20 次请求,桶满了只能装 10 次,剩下 10 次直接拦截 ------ 明明系统刚才有空,却没利用起来,太可惜了。
4. 令牌桶算法:漏桶的 "灵活表弟",突发流量也能 "接住"
漏桶太死板?那令牌桶就是它的 "升级版"------ 像游乐园发令牌,固定速率发令牌,请求拿令牌才能进,还能 "攒令牌",突发流量也不怕。
咋操作?
- 有个 "令牌桶":① 令牌生成速率(每秒发 10 个);② 桶容量(最多存 50 个);
- 系统按速率往桶里放令牌:桶没满就放,满了就扔(不攒太多);
- 请求来的时候拿 1 个令牌:拿到就放行,没拿到就拦截 / 排队;
- 系统闲的时候,桶里会攒令牌 ------ 比如闲了 5 秒,攒了 50 个令牌,突然来 60 个请求,先拿 50 个处理,剩下 10 个等 1 秒(新生成 10 个令牌)再处理,完美接住突发流量!
优点:灵活!兼顾平稳和突发
既能像漏桶一样平稳流量,又能利用空闲资源处理突发 ------API 网关、核心业务接口(比如 "支付回调")用它,基本不会错。
坑点:参数难调!
"令牌生成速率" 和 "桶容量" 得反复试:速率设高了,限流没效果;设低了,浪费资源;桶容量设大了,突发流量可能冲垮系统;设小了,又接不住突发 ------ 新手容易调崩,得结合压测数据来。
总结:选对算法,比啥都重要
算法 | 适合场景 | 核心优势 | 注意坑点 |
---|---|---|---|
简单计数器 | 非核心接口、低精度需求 | 简单易上手 | 临界问题 |
滑动时间窗口 | 核心接口、中等精度需求 | 解决临界问题 | 耗资源 |
漏桶算法 | 下游慢服务(数据库 / MQ) | 流量绝对平稳 | 浪费空闲资源 |
令牌桶算法 | API 网关、核心业务接口 | 灵活应对突发流量 | 参数难调 |
其实限流没有 "万能解",关键是结合业务场景:比如非核心接口用简单计数器省事儿,数据库上游用漏桶保平稳,网关用令牌桶接突发 ------ 你平时项目里用哪种?有没有遇到过 "调参调崩" 的奇葩经历?评论区唠一唠,咱一起避坑~
如果觉得这篇有用,别忘了点赞收藏,下次再遇接口被冲崩,直接翻出来抄作业!