最佳实践
简单需求:固定窗口或滑动窗口。
均匀处理:漏桶(如定时任务)。
允许突发:令牌桶(如API限流)。
高精度控制:滑动日志(小规模场景)。
动态环境:自适应限流(如微服务架构)。
总体看要完成限流的功能,依据场景的特点,最佳实践有 漏斗法 和 令牌桶法。
漏斗法是把请求放到队列,匀速消费。匀速消费保证了不会超过系统载荷,队列长度可以增加限制。一般适用于定时任务。
令牌桶法,通过一定速率生产令牌,放到一个限定长度队列,请求来了需要获取一个令牌(葱队列取出一个)。通过令牌桶的最大长度保证用户的最大的并发访问不会超过系统载荷。一般适用于秒杀场景。
细节介绍
常见的限流算法用于控制系统的请求流量,防止过载。以下是几种主要算法的通俗解释:
1. 固定窗口计数器
原理:像按小时计数的打卡器。比如,设定1秒内最多处理100个请求。每来一个请求,计数器加1,超过100则拒绝。到下一秒时,计数器清零。
问题:窗口切换时可能出现双倍流量。例如,在0:59秒和1:00秒瞬间各涌入100请求,实际1秒内处理了200次。
优点:简单易实现。
缺点:不够精确,临界情况可能超限。
2. 滑动窗口计数器
原理:把时间切成更细的格子。例如,1秒分成10个0.1秒的小窗口。统计时,只看当前时间点往前1秒内的所有小窗口的总请求数。
例子:当前在0.5秒时,统计0.0-0.5秒的请求数,加上前一个完整窗口(0.4秒前的数据可能已过期)。
优点:比固定窗口更平滑,避免双倍流量问题。
缺点:实现稍复杂,需维护多个小窗口数据。
3. 漏桶算法
原理:想象一个漏水的桶。无论水流多猛(请求多快),水只能从桶底以固定速率漏出(处理请求)。如果桶满了(队列容量满),新请求被丢弃。
实现:用队列存储请求,系统按固定速率处理队头请求。
适用场景:需要均匀处理的场景,如定时任务。
缺点:无法应对突发流量,即使系统空闲时也匀速处理。
4. 令牌桶算法
原理:系统以固定速率往桶里放“令牌”,桶有最大容量。请求来了必须拿到令牌才能处理,否则被限流。
例子:桶最多存100个令牌,每秒放10个。若桶满,新令牌被丢弃。突发流量时,可瞬间拿走100个令牌处理。
优点:允许突发流量,适合秒杀等高并发场景。
缺点:需要维护令牌生成和分发逻辑。
5. 滑动日志窗口(精准记录)
原理:严格记录每个请求的时间戳。新请求到来时,删除超出时间窗口的旧记录,再统计剩余数量是否超限。
例子:窗口1秒内最多100次请求。当新请求到达时,清理1秒前的记录,检查当前日志数量。
优点:精确控制,无时间窗口漂移问题。
缺点:消耗内存(存储每个请求时间),高并发时性能低。
6. 自适应限流
原理:根据系统状态(如CPU、响应时间、错误率)动态调整限流阈值。例如,Netflix的算法在系统压力大时自动降低流量上限。
优点:灵活,保护系统不被压垮。
缺点:实现复杂,需监控多项指标。