1. 计数器算法(固定窗口 → 滑动窗口)
把时间切成固定长度的格子,比如每 1 秒一格,每格维护一个计数器。请求进来就加一,超过阈值就拒绝,进入下一格时清零。
java
long windowStart; int count; int limit = 100;
synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now - windowStart >= 1000) { windowStart = now; count = 0; }
return ++count <= limit;
}

致命缺陷是临界突刺。 假设限流每秒 100 个,有人在 0.9s 到 1.0s 之间打进 100 个,又在 1.0s 到 1.1s 之间打进 100 个。两个窗口各自都没超限,但在这 0.2 秒里系统实际扛了 200 个请求,是限额的 2 倍。这样就会导致限流实际上没有限住
滑动窗口就是为了修这个问题。它把 1 秒再切成 N 个小格(比如 10 个 100ms),统计时只看"当前时刻往前推 1 秒"覆盖的那些小格之和。窗口随时间一格一格往前滑,临界突刺被大大削弱。小格切得越细越精确,代价是内存和计算更多。极端情况下可以记录每个请求的时间戳(滑动日志),这样最精确,但也最费内存。

计数器类算法的本质:只管总量,不管请求在时间上的分布。
2. 漏桶算法(Leaky Bucket)
一个底部有小孔的桶:请求像水一样从上面倒进来,桶底以恒定速率往外漏,漏出去的请求才被处理。桶满了,新来的水就溢出,也就是请求被拒绝。
它的核心特点是:不管输入多猛,输出永远是匀速的。它是一个流量整形器,把突发流量"削峰填谷"成平滑流量。

java
long lastLeak; double water; int capacity = 100; double rate = 10; // 每秒漏10个
synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
water = Math.max(0, water - (now - lastLeak) / 1000.0 * rate); // 先算漏掉了多少
lastLeak = now;
if (water + 1 <= capacity) { water++; return true; }
return false;
}
优点 :保护下游效果最好,适合下游处理能力固定、经不起任何抖动的场景,比如调用第三方接口、写数据库。
缺点:太死板。即使系统此刻很空闲,突发请求也只能排队慢慢漏,不能利用空闲资源快速处理,响应延迟会变大。
3. 令牌桶算法(Token Bucket)
反过来想:系统以恒定速率往桶里放令牌 ,桶有容量上限,满了就不再放。请求来了先去桶里拿一个令牌,拿到才能被处理,拿不到就被拒绝或等待。

与漏桶的关键区别在于:空闲时令牌会攒起来 。突发流量到来时,可以一次性消耗掉攒下的全部令牌,瞬间放行一批请求。所以令牌桶限制的是平均速率,同时允许一定程度的突发,突发上限就是桶的容量。
java
long lastRefill; double tokens; int capacity = 100; double rate = 10; // 每秒放10个
synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
tokens = Math.min(capacity, tokens + (now - lastRefill) / 1000.0 * rate); // 懒加载补令牌
lastRefill = now;
if (tokens >= 1) { tokens--; return true; }
return false;
}
注意一个实现细节:真实代码不会开一个定时线程去放令牌,而是在每次请求时根据时间差懒计算应该补多少。 上面的漏桶也是同样的思路。Guava 的 RateLimiter 就是令牌桶,还额外支持预热(SmoothWarmingUp),让系统冷启动时逐步放量。
漏桶 vs 令牌桶
|--------|------------------|--------------------------|
| | 漏桶 | 令牌桶 |
| 控制的对象 | 流出速率 | 流入速率 |
| 突发流量 | 不允许,强制匀速 | 允许,最多突发"桶容量"个 |
| 空闲后的表现 | 和平时一样慢 | 能一口气处理一批 |
| 视角 | 保护下游(我不能被压垮) | 保护自己,同时尽量多干活 |
| 典型应用 | 调用外部接口、消息匀速消费 | API 网关、Guava RateLimiter |