API 限流算法对比:令牌桶、漏桶、滑动窗口怎么选
API Rate Limiting Algorithms Compared: Token Bucket vs Leaky Bucket vs Sliding Window
| David Wang | 2026-08-23T15:48:14
API 限流是后端开发的基本功。这篇文章用代码实例对比三种主流算法的优缺点和适用场景。
API rate limiting fundamentals with code examples comparing algorithms and use cases.
## 为什么需要限流 不限流的 API 就像不设收费站的高速公路。限流保护后端服务不被打爆,是系统自保的基本手段。 ## 四种算法 ### 1. 固定窗口计数器 每个时间窗口(比如 1 秒)内最多允许 N 个请求。实现最简单但有窗口边界突刺问题:第 0.9 秒来 100 个请求,第 1.1 秒又来 100 个,0.2 秒内实际来了 200 个。 ### 2. 滑动窗口 窗口随时间滑动,任何 1 秒时间段内请求数都不超过限制。精确但内存占用高(要记录每个请求的时间戳)。 ### 3. 令牌桶 桶里有固定数量的令牌,每个请求消耗一个,令牌按固定速率补充。允许短时间突发流量(桶里有存量令牌)。最灵活的方案。 ```java public class TokenBucketLimiter { private final int maxTokens; private final double refillRate; private double tokens; private long lastRefill; public synchronized boolean allow() { long now = System.currentTimeMillis(); tokens = Math.min(maxTokens, tokens + (now - lastRefill) * refillRate); lastRefill = now; if (tokens >= 1) { tokens -= 1; return true; } return false; } } ``` ### 4. 漏桶 请求进入桶中,以固定速率流出。桶满了就拒绝。输出速率恒定,保护后端不受突发冲击。 ## 怎么选 | 场景 | 推荐算法 | |------|----------| | 对外 API | 滑动窗口(精确、公平) | | 内部微服务 | 令牌桶(允许突发) | | 消息队列消费 | 漏桶(恒定速率) | | 简单场景 | 固定窗口 | ## Redis 分布式限流 生产环境用 Redis Lua 脚本实现令牌桶,保证原子性: ```lua local key = KEYS[1] local max_tokens = tonumber(ARGV[1]) local refill_rate = tonumber(ARGV[2]) local now = tonumber(ARGV[3]) local data = redis.call('HMGET', key, 'tokens', 'last_refill') local tokens = tonumber(data[1]) or max_tokens local last_refill = tonumber(data[2]) or now tokens = math.min(max_tokens, tokens + (now - last_refill) * refill_rate) if tokens >= 1 then tokens = tokens - 1 redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now) redis.call('EXPIRE', key, 60) return 1 else redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now) redis.call('EXPIRE', key, 60) return 0 end ``` 限流看起来简单,但选对算法、用对工具,差距很大。
Four rate limiting algorithms: Fixed Window (simple, boundary burst), Sliding Window (precise, memory-heavy), Token Bucket (flexible, allows bursts), Leaky Bucket (constant output). Redis Lua script for distributed token bucket.