在高并发架构中限流是保障服务高可用的“安全阀”。当上游流量洪峰超出下游服务的处理极限时限流机制通过精准的拒绝、排队或延迟策略防止系统因资源耗尽而发生雪崩。本文将从限流的分类入手深入剖析单机限流的核心算法逻辑并详解分布式全局限流的两种主流架构为你构建一套完整的限流知识体系。为什么需要限流在分布式系统中限流Rate Limiting是下游服务为了防止被上游请求压垮而采取的一种自我保护机制。目标控制请求速率保证系统稳定性分类:频控控制用户在N秒内只可执行M次操作。单机限流某服务的每台服务器在1s内最多可处理个请求。全局限流某服务在1s内总共可处理M个请求。单机自适应限流某服务的每台服务器根据自身服务状况使用各种自动化算法动态判断是否限制请求。频控用户维度下的限流场景频控主要用于防止恶意刷接口或限制用户行为。N秒内只能执行1次实现原理使用SETNX命令。如果设置成功说明是首次操作如果失败说明在时间窗口内已操作过。// 对应 Redis 命令: SET key 0 EX 30 NX Boolean result redisTemplate.opsForValue().setIfAbsent(key, 0, 30, TimeUnit.SECONDS);N秒内最多执行 M 次当涉及到“计数”和“过期时间设置”两个动作时必须保证原子性否则可能出现 Key 永久存在或计数错乱。实现逻辑使用INCR计数当返回值为 1 时设置过期时间。判断逻辑:count ≤ M → 放行count M → 限流local count redis.call(INCR, KEYS[1]) if count 1 then redis.call(EXPIRE, KEYS[1], ARGV[1]) -- ARGV[1] 为过期秒数 end return count单机限流控制“单台机器”的处理能力固定时间窗口原理将时间轴切分为固定长度的窗口如1s每个窗口维护一个计数器。执行流程定位窗口根据当前时间戳计算出所属的窗口ID例如当前秒数。获取计数器从内存中获取该窗口ID对应的计数器。判断与扣减如果计数器值 0计数器减1允许请求通过。如果计数器值 0拒绝请求。缺点无法防止时间窗口边界附近的流量暴增。举例假设限制1s内100个请求。在0.9s时涌入100个请求在1.1s时又涌入100个请求。虽然每个窗口都没超限但在1.0s前后的200ms内系统实际承受了200个请求导致瞬间流量翻倍。滑动时间窗口原理将时间窗口划分为更小的格子。窗口随着时间滑动丢弃过期的槽位累加新槽位的计数。流程划分时间槽将时间线按小粒度如50ms划分为独立的时间槽。定义滑动窗口限流窗口由最近的N个槽如20个组成随时间推移不断向后滑动。请求判定当请求到来时在当前窗口内查找是否存在计数大于0的槽。若找到将该槽计数减1允许请求通过。若未找到所有槽计数均为0丢弃请求触发限流。优点解决了窗口边界流量暴增问题精度更高。缺点但需要维护更多的槽位数据内存和CPU开销相对较大。漏桶算法原理请求像水一样流入桶中桶以恒定的速率出水处理请求。无论流入速率多快流出速率永远固定。执行流程请求到达检查漏桶队列是否已满。判断与入队如果桶未满将请求加入队列尾部等待处理。如果桶已满直接拒绝请求。匀速处理一个独立的消费者线程以固定的时间间隔如每10ms从队列头部取出一个请求进行处理。特点强行整形将突发流量平滑为恒定流量按照固定的速率被处理。缺点无法应对突发流量。令牌桶算法原理系统以恒定速率向桶中放入令牌桶有容量上限。存满新生成的令牌会被丢弃请求处理前必须先获取令牌无令牌则拒绝。适用场景:对流量精度高并且容忍短期突发流量。优点既控制长期的平均速率又支持短期突发流量。缺点实现复杂度较高。要维护令牌的生成存储消耗全局限流基于Redis的集中式限流不适合请求量巨大的服务逻辑把单机的固定窗口计数器搬到 Redis 上。流程所有服务器实例在处理请求前先去 Redis 做一次INCR。如果 Redis 返回的值超过总限额本地拦截。优点数据强一致限流精准。缺点引入额外网络调用Redis本身可能成为性能瓶颈影响了业务服务的稳定性。基于时间片的动态反馈限流适合请求量大的服务对请求进行粗略筛选。核心逻辑上报统计 - 计算比例 - 下发丢弃率。流程统计上报各服务实例周期性如每1s将本地的请求数、延迟等统计信息上报到消息队列。全局聚合日志收集器消费消息计算整个集群在当前时间片的实际QPS。决策下发限流服务器对比实际QPS与目标阈值计算丢弃率DropRate。公式DropRate (实际QPS - 目标QPS) / 实际QPS本地执行各实例接收最新的DropRate在本地进行概率性丢弃。优点避免了每次请求都访问Redis性能极高。缺点存在秒级的控制延迟无法做到毫秒级的精准控制适合对实时性要求不苛刻的场景。