接口限流怎么选:固定窗口、滑动窗口与令牌桶的落地对比

举报
yd_236134918 发表于 2026/11/07 06:24:43 2026/11/07
【摘要】 固定窗口简单但有边界突刺,滑动窗口平滑但成本更高,令牌桶允许短暂突发最适合保护下游。本文结合后端落地经验,对比三种限流算法的原理、适用场景与实现要点,并给出选型建议。

做后端接口,最怕的不是请求多,而是请求来得没有节奏。一次秒杀、一次重试风暴、一个失控的定时任务,都能把原本正常的服务打到超时。限流就是给接口装一道闸:超过承受能力的流量,先挡在门外,保住核心链路。

一、固定窗口:最简单,也最容易被打穿

固定窗口把时间切成一段一段,比如每分钟最多放行 1000 次。实现只需要一个计数器加一个过期时间,Redis 里一条 INCR 就能搞定。

问题出在窗口边界上。第 59 秒来了 1000 次,下一窗口的第 0 秒又来了 1000 次,两秒之内实际放行了 2000 次,等于限流在边界处失效了一半。流量越是集中,这个毛刺越明显。

适合:内部低频接口、后台管理类接口、对突发不敏感的场景。

二、滑动窗口:把边界磨平

滑动窗口把一个大窗口切成若干小格子,只统计最近一个窗口内的小格子之和。比如 1 分钟切成 6 个 10 秒格子,每次请求都看最近 6 格的总量。边界处的突刺被摊平了,曲线平滑很多。

代价是实现变复杂:要维护多个格子的计数,内存和计算都比固定窗口高一个量级。格子越细越平滑,成本也越高,工程上一般取 5 到 10 格就够了。

适合:对外 API、按量计费的接口、对平滑性有要求的场景。

三、令牌桶:允许突发,但守住平均速率

令牌桶以固定速率往桶里放令牌,桶满了就不再放;请求到来时取一枚令牌,没有令牌就拒绝。平时攒下的令牌可以在突发时一次性用掉,所以它允许短暂的突发,但长期平均速率被死死按住。

这正好匹配真实流量:大多数业务不是匀速的,而是平时平稳、偶尔尖峰。令牌桶既不误伤正常尖峰,又能挡住持续超载。

令牌桶的核心逻辑只有三步:第一步,每次请求先按流逝时间补充令牌,补充量等于流逝秒数乘以补充速率 rate,上限为桶容量 capacity;第二步,令牌数大于等于 1 时扣 1 枚并放行;第三步,令牌不足 1 枚时拒绝请求并返回 429。补充速率 rate 决定长期承载能力,桶容量 capacity 决定能容忍多大的突发,capacity 设得越大,突发越放得开,风险也越大。生产环境建议直接用成熟的限流组件实现,不要自己手写。

四、三种算法怎么选

  • 只要“别超量”,实现越简单越好:固定窗口。
  • 对外暴露、按量计费、怕边界毛刺:滑动窗口。
  • 流量有尖峰、要保护下游数据库和第三方依赖:令牌桶。
  • 分布式场景下,三种算法都不要在单机内存里做计数,用 Redis 集中计数,或者用网关层统一限流,否则每个节点各限各的,总量会失控。

五、落地时容易踩的坑

  1. 限流键选错:按用户限流还是按接口限流,粒度不同效果天差地别;一个大客户的突发不应该拖垮所有用户。
  2. 只限流不降级:被拒绝的请求要返回明确的 429 和重试建议,而不是让调用方无差别重试,否则重试本身会变成第二波洪峰。
  3. 阈值拍脑袋:先压测出单机和下游的真实承载能力,再倒推阈值;上线后按监控数据定期复核。
  4. 忽略预热:服务刚启动、缓存还是冷的时候,满速放行等于自杀,启动阶段可以适当收紧。

结语

限流没有银弹,只有取舍。固定窗口胜在简单,滑动窗口胜在平滑,令牌桶胜在兼顾突发与均值。先搞清楚自己的流量形态,再选算法、再定阈值,比纠结哪种算法“更高级”重要得多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。