当前位置: 首页 > java >正文

限流算法详解:固定窗口、滑动窗口、令牌桶与漏桶算法全面对比

限流(Rate Limiting)是保障系统稳定性和服务质量的关键机制,尤其在高并发、突发流量、攻击防护等场景中至关重要。

本文将详细介绍四种主流限流算法:

  • 固定窗口(Fixed Window)

  • 滑动窗口(Sliding Window)

  • 令牌桶(Token Bucket)

  • 漏桶算法(Leaky Bucket)

我们将从原理、实现方式、优缺点和适用场景四个维度进行深入分析和对比。


一、固定窗口(Fixed Window)

原理:将时间划分为固定长度窗口,统计每个窗口内的请求数,超过上限则拒绝。

实现方式(常用 Redis INCR + EXPIRE):

key = f"req:{user_id}:{current_minute}"
count = redis.incr(key)
if count == 1:redis.expire(key, 60)
if count > threshold:reject()

优点

  • 实现简单,性能高。

  • Redis 支持天然适配。

缺点

  • 临界突刺问题:在两个窗口交界点,可能放行两倍请求。

适用场景

  • 精度要求不高的接口。

  • 管控类后台系统。


二、滑动窗口(Sliding Window)

1. 滑动日志(Sliding Log)

原理:记录每次请求时间戳,实时清理超出时间窗口的旧请求,判断窗口内数量。

优点

  • 流量限制更精确。

  • 避免突刺。

缺点

  • 需要维护时间戳列表,内存消耗较大。

2. 滑动窗口计数器(Sliding Window Counter)

原理:将一个窗口拆分为多个小窗口,每个子窗口统计请求数,根据时间加权合并。

优点

  • 性能和精度之间较好平衡。

适用场景

  • 高并发、登录、敏感操作等流控要求较高的业务。


三、令牌桶算法(Token Bucket)

原理

  • 系统以固定速率放入“令牌”到桶中;

  • 每次请求需要“取一个令牌”才能通过;

  • 桶容量有限,超过上限的令牌被丢弃;

  • 若桶为空,请求被限流(或排队等)。

示意图

+----------+
| 令牌桶    |
|          |<-- 固定速率生成令牌
|   [ ]    |
+----------+↓请求来取令牌 -> 成功 or 被限流

优点

  • 支持突发流量(令牌可积累)。

  • 灵活控制平均速率与突发能力。

  • Guava / Nginx 都有成熟实现。

缺点

  • 实现较复杂。

  • 依赖精准时间调度。

适用场景

  • 接口限频,突发高并发业务。

  • LLM API 限流 / OpenAI、Stripe 等系统。


四、漏桶算法(Leaky Bucket)

原理

  • 所有请求先进入一个桶中;

  • 桶以固定速率“漏水”处理请求;

  • 桶满时,新请求要么被丢弃,要么排队等待。

示意图

请求 → 桶(队列) → 以恒定速率处理(漏水)↑桶满则拒绝或排队

实现方式

  • 可以用一个队列存储请求;

  • 后台定期以固定速率出队并处理请求。

优点

  • 平滑处理请求流量,保持处理速率稳定。

  • 防止服务被瞬时流量压垮。

缺点

  • 不支持突发流量(桶中积压,排队延迟)。

  • 实现复杂度略高于令牌桶。

适用场景

  • 网关、负载均衡器的请求调度。

  • 强调处理速率恒定的后台任务系统。


五、算法对比总结

特性固定窗口滑动窗口令牌桶漏桶
实现复杂度⭐(简单)⭐⭐(中等)⭐⭐⭐(中高)⭐⭐(中等)
限流精度中等
是否支持突发请求
是否平滑
是否常用✅(Redis)✅(Sentinel)✅(Guava、Nginx)✅(调度系统)

六、实战建议

  • 简单限流场景(如后台管理):使用 固定窗口 + Redis 即可。

  • 高并发接口限频:推荐 滑动窗口令牌桶,后者更适合突发请求。

  • 需要平滑处理队列任务:选择 漏桶算法


七、结语

限流并不是一刀切的“阻止请求”,而是为系统争取喘息空间。不同的限流算法背后体现的是不同的设计哲学与业务权衡。

选对限流算法,既可以保护系统,又能优化用户体验。

http://www.xdnf.cn/news/16735.html

相关文章:

  • 实现implements InitializingBean, DisposableBean 有什么用
  • 【2025/07/30】GitHub 今日热门项目
  • arkui 动画曲线
  • 分布式搜索和分析引擎Elasticsearch实战指南
  • SpringBoot 2.7.18 升级 3.4.6
  • duiLib 自定义资源目录
  • C#垃圾回收机制:原理与实践
  • 极致业务弹性 密度性能双管齐下—联想问天 WR5220 G5 服务器测试
  • Spring AI 海运管理应用第2部分
  • Android Animation Transitions:打造流畅的用户体验
  • 全栈:SSH和SSM和Springboot mybatisplus有什么区别?
  • WPFC#超市管理系统(3)商品管理
  • 如何判断一个数据库是不是出问题了?
  • 2025年6月电子学会青少年软件编程(C语言)等级考试试卷(二级)
  • SpringBoot学习 |springboot概念+微服务架构
  • Python并发与性能革命:自由线程、JIT编译器的深度解析与未来展望
  • 滚珠导轨在电子制造中的流畅性优势
  • Electron + Fabric 打包遇到error LNK2001
  • 从数据到预测:InfluxDB+Prophet时间序列分析案例实战
  • 观远 ChatBI 完成 DeepSeek-R1 大模型适配:开启智能数据分析跃升新篇
  • 工作笔记-----FreeRTOS中的lwIP网络任务为什么会让出CPU
  • Ⅹ—6.计算机二级综合题15---18套
  • 前端安全防护:XSS、CSRF与SQL注入漏洞深度解析与防御
  • 在macOS上使用VS Code和Clang配置C++开发环境
  • Thales靶机
  • kali Linux 2025.2安装教程(解决安装失败-图文教程超详细)
  • jmeter--While控制器--循环直到接口响应符合条件
  • cmake项目基本demo
  • 深度学习(鱼书)day06--神经网络的学习(后两节)
  • C语言数据结构(1)顺序表专题2.顺序表的应用