1. 限流策略概述
在分布式系统和高并发场景中,限流是保障系统稳定性的重要手段。作为一名经历过多次流量洪峰的开发者,我深刻理解合理限流策略对系统的重要性。限流本质上是通过控制请求通过的速率,防止系统因突发流量而过载崩溃。
常见的四种限流算法各有特点:
- 计数器算法:实现简单但精度较低
- 滑动窗口:提高了计数精度
- 漏桶算法:强制恒定速率输出
- 令牌桶算法:兼顾突发流量处理能力
在实际项目中,我们需要根据业务特点选择合适的算法。比如电商秒杀适合用令牌桶,而API网关可能更适合滑动窗口。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 限流算法原理深度解析
2.1 计数器算法实现细节
计数器算法虽然简单,但在实现时仍需注意几个关键点:
java复制public class CounterLimiter {
private final long interval; // 时间窗口长度(毫秒)
private final long limit; // 窗口内最大请求数
private long counter = 0; // 当前计数
private long windowStart; // 窗口开始时间
public CounterLimiter(long interval, long limit) {
this.interval = interval;
this.limit = limit;
this.windowStart = System.currentTimeMillis();
}
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now > windowStart + interval) {
// 进入新时间窗口
windowStart = now;
counter = 0;
}
if (counter < limit) {
counter++;
return true;
}
return false;
}
}
注意:计数器算法在分布式环境下需要使用Redis等分布式计数器,单机实现仅适用于单体应用。
临界值问题是计数器算法的主要缺陷。假设设置每秒100个请求的限流:
- 第0.9秒突然涌入100个请求
- 第1.1秒又涌入100个请求
虽然两个1秒窗口都没超限,但实际在0.2秒内处理了200个请求,可能导致系统过载。
2.2 滑动窗口算法优化
滑动窗口通过细分时间窗口来解决临界问题。典型实现是将1秒窗口划分为10个100毫秒的子窗口:
java复制public class SlidingWindow {
private final long windowSize; // 窗口大小(毫秒)
private final int shardNum; // 子窗口数量
private final long shardSize; // 子窗口大小(毫秒)
private final long limit; // 窗口限制数
// 子窗口计数器数组
private final AtomicInteger[
