《一篇文章搞懂常见限流算法:固定窗口、滑动窗口、漏桶和令牌桶》 一、为什么需要限流先从业务场景引入在高并发系统中如果瞬时流量超过系统承载能力可能会导致接口响应变慢、线程池耗尽、数据库连接打满甚至服务雪崩。限流的目的就是在流量进入系统之前做控制保护核心服务稳定运行。常见场景包括秒杀、抢购、热点活动API 网关限制访问频率防止恶意请求或爬虫保护下游服务、数据库、第三方接口多租户系统中限制单个用户或应用的资源占用二、什么是限流限流就是限制单位时间内允许通过的请求数量。当请求超过阈值时系统可以选择拒绝请求、排队等待、降级处理或者返回提示信息。比如限制某个接口每秒最多处理 100 个请求限制某个用户每分钟最多发送 10 条短信限制某个 IP 每小时最多调用 1000 次 API三、固定窗口计数器固定窗口计数器是最简单的限流算法。它把时间划分成固定窗口比如 1 秒一个窗口然后统计当前窗口内的请求数量。如果数量超过阈值就拒绝请求。示例限制每秒最多 100 个请求00:00:01 - 00:00:02 这个窗口内计数不能超过 100优点实现简单内存占用低性能好缺点有临界问题比如限制每秒 100 次请求第 1 秒的最后 10ms 进入 100 个请求第 2 秒的前 10ms 又进入 100 个请求从窗口角度看都没超限但在 20ms 内实际通过了 200 个请求瞬时流量翻倍。四、滑动窗口计数器滑动窗口是对固定窗口的优化。它把一个大窗口拆成多个小窗口然后随着时间推移不断滑动。比如把 1 分钟拆成 6 个 10 秒的小窗口每次统计最近 1 分钟内所有小窗口的请求总数。优点比固定窗口更平滑能缓解临界突刺问题统计结果更接近真实流量缺点实现比固定窗口复杂小窗口越多统计越精确但内存和计算成本越高五、漏桶算法漏桶算法可以把系统想象成一个桶请求像水一样进入桶桶以固定速率漏水也就是处理请求如果桶满了新的请求会被丢弃或拒绝优点输出流量非常平滑可以保护下游服务适合削峰填谷缺点不能很好应对突发流量即使系统此时有空闲能力也只能按固定速率处理请求可能需要排队增加延迟适用场景保护下游服务消息队列消费限速第三方接口调用限速六、令牌桶算法令牌桶是实际业务中非常常用的限流算法。它的核心思想是系统按固定速率往桶里放令牌请求到来时必须拿到令牌才能通过没有令牌时请求被拒绝或等待桶有容量上限令牌满了之后不会继续增加和漏桶不同的是令牌桶允许一定程度的突发流量。比如令牌生成速率每秒 100 个桶容量200 个如果系统空闲了一段时间桶里最多可以积累 200 个令牌。下一秒突然来了 200 个请求也可以一次性放行。优点支持突发流量平均速率可控比漏桶更灵活应用非常广泛缺点实现稍复杂需要维护令牌生成时间、桶容量、剩余令牌数适用场景API 网关限流用户访问频率控制分布式服务接口保护Guava RateLimiter、Sentinel 等组件中常见七、漏桶和令牌桶的区别对比点漏桶算法令牌桶算法控制对象控制请求流出速度控制请求是否能通过处理速度固定速率平均速率固定可突发突发流量不友好支持一定突发典型作用平滑流量限制平均速率适用场景削峰、保护下游API 限流、网关限流漏桶强调以固定速率处理请求令牌桶强调以固定速率生成访问资格因此令牌桶更适合允许短时间突发的业务场景。八、分布式限流如果是单机服务限流可以直接在内存中完成。但在分布式系统中一个服务通常会部署多个实例如果每个实例都单独限流就可能导致整体限流失效。比如接口限制每秒 100 次服务部署了 5 台机器如果每台机器都限制 100 次最终整体可能变成每秒 500 次所以分布式限流通常需要借助 Redis、网关或专门的限流组件。常见方案Redis Lua 脚本实现原子计数API 网关统一限流Sentinel、Hystrix、Resilience4j 等组件Nginx 限流模块九、实际选择建议简单接口限流固定窗口计数器对精度要求更高滑动窗口需要平滑处理请求漏桶算法允许突发但限制平均速率令牌桶算法分布式系统Redis、网关或 Sentinel限流的本质不是简单地拒绝请求而是在系统承载能力和用户体验之间取得平衡。固定窗口实现简单但存在临界突刺问题滑动窗口更精确漏桶适合平滑流量令牌桶则在控制平均速率的同时允许一定突发流量。实际项目中需要结合业务场景、系统容量、部署架构和用户体验选择合适的限流方案。