主题
概念卡片:限流算法
一句话机制:限流是「有损服务」的保护手段——超过阈值就拒绝/排队/降级,避免瞬时流量打垮系统;核心是三种算法:滑动窗口(时间窗口内计数)、漏桶(固定速率流出,平滑流量)、令牌桶(固定速率放令牌,允许突发)。
三种限流算法
| 算法 | 原理 | 特点 | 适用 |
|---|---|---|---|
| 计数器 | 单位时间窗口内计数 | 粗糙,窗口边界会突刺 | 最简单场景 |
| 滑动窗口 | 窗口随时间滑动,精确统计窗口内请求 | 平滑计数 | Sentinel 采用 |
| 漏桶 | 固定速率流出,桶满溢出(拦截或丢弃) | 平滑突发流量,不能突发 | 流量整形 |
| 令牌桶 | 固定速率放令牌,请求需取令牌,桶满令牌丢弃 | 允许突发(令牌可积累) | 主流(Guava RateLimiter) |
关键代码示例(Guava 令牌桶)
java
RateLimiter rateLimiter = RateLimiter.create(10); // 每秒 10 个令牌(QPS)
if (rateLimiter.tryAcquire()) { // 尝试取一个令牌
System.out.println("允许通过");
} else {
System.out.println("被限流了");
}令牌桶的两个关键参数
| 参数 | 含义 |
|---|---|
rate | 生成令牌速度(如 rate=2 → 每秒 2 个令牌) |
burst | 桶容量(如 burst=10 → 最多积累 10 个令牌,支持突发) |
限流的常见维度
- 限制总并发数(数据库连接池、线程池)
- 限制瞬时并发数(nginx
limit_conn) - 限制时间窗口平均速率(nginx
limit_req、Guava RateLimiter) - 限制远程接口调用速率、MQ 消费速率
不变量(必须成立的约束)
- 限流是有损的(被限流的用户会不开心),但比「全部不可用」好。
- 漏桶不能突发(恒定速率),令牌桶能突发(令牌可积累),高并发秒杀场景优先令牌桶。
- 限流要评估好阈值,乱用会误伤正常流量、影响体验。
踩坑案例
- 现象:秒杀瞬间流量打满,用漏桶限流,导致正常用户也被排队。 原因:漏桶恒定速率,无法应对「允许短时突发」的诉求。解决:改用令牌桶(积累的令牌吸收突发),或令牌桶 + 漏桶组合。
常见误解
- 以为限流能保证系统永不挂 → 限流是「有损保护」,只是把「全挂」变成「部分拒绝」。
- 以为漏桶和令牌桶一样 → 漏桶平滑但不能突发,令牌桶允许突发,场景不同。
关联
- Sentinel 限流落地:概念卡片:Sentinel熔断限流降级
- 缓存选型:概念卡片:缓存技术选型与多级缓存
- 源:
B40-资源/语雀-Code-Summary/Middleware/Limit&Balance/LimitOther(限流策略 + Sentinel vs Hystrix 对比)