3467 字
约 11 分钟
7
限流详解:常见业务场景与四种核心算法

限流详解:常见业务场景与四种核心算法

一、什么是限流

限流,顾名思义就是:

限制进入系统的流量。

在高并发系统中,如果短时间内大量请求同时进入服务器,很容易导致:

线程池耗尽
数据库连接池耗尽
CPU 飙高
内存压力增大
下游服务被打垮
最终导致系统雪崩

所以限流的核心目的就是:

通过限制请求速率、并发量或者资源使用量,保护系统不被瞬时流量冲垮。

例如系统最多只能承受:

1000 QPS

那么即使瞬间进来:

5000 QPS

也只允许其中一部分请求进入系统,其余请求可以:

直接拒绝
排队等待
降级处理
返回友好提示

因此,限流本质上是一种:

系统保护机制。


二、为什么需要限流

系统的资源永远都是有限的。

例如:

CPU 有上限
线程数有上限
数据库连接数有上限
Redis 连接数有上限
第三方 API 调用次数有上限

如果不做限流,当请求量超过系统承载能力时,就会出现:

请求越来越慢
↓
请求开始堆积
↓
线程被占满
↓
数据库连接耗尽
↓
更多请求超时
↓
系统雪崩

所以限流的核心思想可以理解成:

宁愿拒绝一部分请求,也不要让整个系统全部挂掉。


三、常见的限流业务场景

1. 短信验证码 / 邀请码发送

例如:

用户注册发送验证码,1 分钟只能发送一次。

可以限制:

同一个手机号:
1 分钟最多发送 1 次

例如 Redis:

sms:13800138000

设置:

TTL = 60 秒

如果 Key 已经存在:

请勿频繁发送验证码

这种属于:

用户维度限流。


2. 第三方接口调用次数限制

例如第三方平台规定:

每天最多调用 10000 次

那么系统就需要维护:

third_api:2026-09-01

记录当天已经调用多少次。

例如:

当前调用次数:9999

还能调用。

如果:

当前调用次数:10000

后续请求就需要:

拒绝
延迟
排队
第二天再执行

这种属于:

资源配额限流。


3. 防止突发流量打垮服务

假设服务器正常只能承受:

2000 QPS

突然因为:

秒杀
热点新闻
营销活动
爬虫
恶意请求

流量暴涨到:

20000 QPS

如果所有请求直接进入系统,很容易把服务器打挂。

因此可以限制:

最多允许 2000 QPS

其余请求:

拒绝
排队
降级

这种属于:

系统入口限流。


4. 接口防刷

例如:

登录接口
注册接口
评论接口
领取优惠券
抽奖接口
点赞接口

可以限制:

同一个 IP:
1 分钟最多请求 100 次

同一个用户:
1 秒最多请求 5 次

防止:

爬虫
恶意脚本
接口攻击
重复提交

5. 秒杀系统

例如:

库存只有 1000 件

但瞬间有:

10 万用户请求

没有必要让所有请求都进入数据库。

可以在网关层直接限流:

只允许部分请求进入核心系统

配合:

缓存
消息队列
库存预扣

保护数据库。


6. API 网关限流

例如:

/user/**
/order/**
/pay/**

不同接口设置不同 QPS。

比如:

普通查询接口:
1000 QPS

订单创建接口:
300 QPS

支付接口:
100 QPS

这种属于:

接口维度限流。


7. 多租户 / SaaS 系统

例如:

普通用户:
100 次 / 分钟

VIP 用户:
1000 次 / 分钟

企业用户:
10000 次 / 分钟

这类属于:

配额型限流。


四、常见限流维度

实际业务中,限流往往不仅仅是限制整个系统。

还可以按不同维度进行。

例如:

系统级别
接口级别
用户级别
IP 级别
设备级别
租户级别
手机号级别
第三方平台级别

例如:

/user/login

同一个 IP:
1 分钟 100 次

同一个账号:
1 分钟 10 次

可以同时存在多个限流规则。


五、常见限流算法

常见的限流算法主要有四种:

固定窗口
滑动窗口
漏桶算法
令牌桶算法

六、固定窗口算法

固定窗口是最简单的一种限流算法。

例如:

1 分钟最多请求 100 次

把时间划分成一个个固定窗口:

10:00 - 10:01
最多 100 次

10:01 - 10:02
最多 100 次

在一个窗口里面维护一个计数器:

count++

如果:

count <= 100

允许访问。

否则拒绝。

到了下一个窗口:

count = 0

重新计数。

例如 Redis:

limit:user:1001:10:00

每请求一次:

INCR

并设置:

EXPIRE 60

固定窗口的问题

最大的问题是:

窗口边界可能出现双倍流量。

例如限制:

1 分钟最多 100 次

用户在:

10:00:59

瞬间请求 100 次。

紧接着:

10:01:00

窗口重置。

又请求 100 次。

于是:

1 秒左右
实际进入了 200 个请求

这就是:

临界值问题。

所以固定窗口实现简单,但流量控制不够平滑。


七、滑动窗口算法

滑动窗口是固定窗口的优化。

固定窗口:

10:00 - 10:01
10:01 - 10:02

窗口是死的。

滑动窗口则始终统计:

当前时间往前推一段时间。

例如:

当前时间 10:01:20

统计:

10:00:20 - 10:01:20

这一分钟里面的请求数量。

假设规则:

最近 60 秒最多 100 次

那么每次请求进来:

删除 60 秒以前的数据
↓
统计最近 60 秒请求数
↓
小于 100
允许
↓
大于等于 100
拒绝

Redis 中非常适合使用:

ZSET

实现。

例如:

score = 请求时间戳
member = requestId

然后:

ZREMRANGEBYSCORE

删除过期数据。

再:

ZCARD

统计窗口内请求数。


滑动窗口的优点

相比固定窗口:

更加准确
更加平滑
不会出现明显的窗口边界问题

缺点是:

需要记录更多请求数据
实现成本更高

八、漏桶算法

漏桶算法可以想象一个水桶。

请求就像水:

请求
↓↓↓↓↓↓↓↓
┌──────────┐
│          │
│   水桶   │
│          │
└─────┬────┘
      │
      ↓
固定速度流出

请求可以快速进入桶里。

但是系统处理请求的速度是固定的。

例如:

桶容量:100
流出速度:10 个 / 秒

即使瞬间来了:

100 个请求

系统也只会按照:

10 个 / 秒

慢慢处理。

如果桶满了:

后续请求直接拒绝

所以漏桶算法最大的特点:

强制请求按照稳定速率流出。

特别适合:

保护下游系统
消息发送
调用第三方接口
稳定消费速度

九、漏桶算法的特点

优点:

流量非常平滑
可以很好保护下游服务

缺点:

不允许突发流量。

即使系统现在很空闲:

突然来了 100 个请求

也只能:

一个一个按照固定速度处理

所以对于需要允许一定突发能力的系统,漏桶会显得比较严格。


十、令牌桶算法

令牌桶是实际系统中非常常见的一种限流算法。

想象有一个桶:

┌──────────┐
│ ● ● ● ● │
│ ● ● ●   │
│          │
└──────────┘

桶里面放的是:

令牌 Token

系统按照固定速率向桶里放令牌。

例如:

每秒生成 10 个 Token

每个请求进来必须:

拿到 1 个 Token

才能执行。

如果拿不到:

拒绝请求

令牌桶为什么允许突发流量

假设:

桶容量 = 100
令牌生成速度 = 10 / 秒

如果系统一段时间没有请求:

桶里面积累了 100 个 Token

突然来了:

100 个请求

它们可以瞬间拿走:

100 个 Token

全部执行。

然后后续请求只能按照:

10 个 / 秒

继续执行。

所以:

令牌桶既能限制长期平均速率,又允许一定程度的瞬时突发流量。

这也是为什么很多系统非常喜欢令牌桶。


十一、漏桶和令牌桶的区别

这是非常经典的面试题。

漏桶:

请求进入桶
↓
按照固定速率出去

核心控制的是:

输出速度。

令牌桶:

系统生成 Token
↓
请求抢 Token
↓
抢到才能执行

核心控制的是:

请求是否获得执行资格。

最大的区别:

漏桶:
不允许明显突发流量

令牌桶:
允许一定突发流量

可以简单理解:

算法 是否支持突发流量
固定窗口 支持,但可能失控
滑动窗口 一定程度支持
漏桶 基本不支持
令牌桶 支持

十二、四种算法怎么选择

可以简单这么选。

固定窗口

适合:

实现简单
精度要求不高
业务量较小

例如:

短信验证码:
1 分钟一次

滑动窗口

适合:

接口防刷
用户请求频率控制
对限流准确性要求较高

例如:

最近 1 分钟最多请求 100 次

漏桶

适合:

必须严格控制下游处理速度

例如:

第三方接口只能稳定接受
100 请求 / 秒

令牌桶

适合:

系统入口限流
API 网关
微服务限流
秒杀
允许短时间突发流量

实际工程中非常常见。


十三、实际业务如何选择

前面三个需求可以直接对应。

用户注册发送邀请码,一分钟一次

建议:

Redis Key + TTL

或者:

固定窗口

因为:

业务简单
不要求毫秒级精度

第三方接口每天只能调用 1 万次

可以使用:

每日计数器
+
固定窗口

例如:

third-api:20260901

每天重置。


防止突发流量打垮服务器

更适合:

令牌桶

例如:

平时允许 1000 QPS
桶容量 2000

这样:

长期平均速度被限制
+
系统又能承受一定突发流量

这是网关、微服务入口非常常见的方案。


十四、限流一般放在哪里

实际系统中,限流可以存在多个层级:

用户
↓
Nginx
↓
API Gateway
↓
微服务
↓
具体接口
↓
数据库 / 第三方服务

例如:

Nginx
负责粗粒度流量控制

Gateway
负责用户、IP、接口维度限流

Service
负责具体业务限流

Redis
负责分布式限流计数

通常不会只做一层限流。


十五、限流之后怎么处理请求

触发限流并不一定只能直接报错。

常见处理方式包括:

直接拒绝
排队等待
快速失败
降级处理
进入消息队列
返回缓存数据
稍后重试

例如 HTTP 接口可以返回:

HTTP 429 Too Many Requests

表示:

请求过于频繁。


十六、限流的核心总结

限流的本质就是:

控制进入系统或者进入某个资源的请求速度,避免流量超过系统承载能力。

常见算法:

固定窗口
滑动窗口
漏桶
令牌桶

核心区别:

固定窗口:
简单计数

滑动窗口:
精确统计最近一段时间

漏桶:
固定速度处理请求

令牌桶:
固定速度产生令牌,允许一定突发流量

实际业务场景:

短信验证码防刷
登录接口防刷
第三方 API 配额
秒杀流量控制
API 网关
微服务保护
爬虫防护
支付接口保护
多租户配额
资源访问限制

如果只记住一句话:

限流不是为了让系统处理更多请求,而是在系统能力有限的情况下,控制请求进入速度,从而保护整个系统的稳定性。

限流详解:常见业务场景与四种核心算法
http://www.clxhxhhr.top/posts/408/
作者
clxstart
发布于
2026-09-02
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。