← 返回题目列表

令牌桶和漏桶算法有什么区别?分别适合什么场景?

高频 中等 第 6 / 26 题 更新于 2026/07/28
令牌桶漏桶限流算法突发流量

简化版

令牌桶按固定速率生成令牌,请求拿到令牌才能通过,允许一定突发流量;漏桶按固定速率漏水,请求进入桶后匀速处理,更强调平滑输出。令牌桶适合允许短时突刺的接口,漏桶适合需要稳定下游处理速率的场景。

详细版

两者核心差异:

维度令牌桶漏桶
控制方式控制请求是否能拿到令牌控制请求按固定速率流出
突发流量允许桶内令牌支持突发通常会排队或丢弃,输出平滑
用户体验短时突发更友好延迟更可控但可能排队
适用场景API 限流、网关限流、允许 burst消息削峰、下游匀速写入、流量整形

令牌桶参数包括令牌生成速率和桶容量。漏桶参数包括漏出速率和桶大小。面试时要注意:令牌桶允许瞬时流量超过平均速率,但长期平均受生成速率限制;漏桶更像把不均匀请求整形成稳定速率。

完整版教学

一、先把两个桶想成两种交通规则

令牌桶像高速入口发通行证。系统按固定速率发令牌,车来了必须拿到通行证才能上高速。如果前一段时间车少,令牌会攒起来,后面突然来一小波车,可以快速通过。这就是令牌桶支持突发流量的原因。

漏桶像一个底部有小孔的水桶。水可以突然倒进来,但只能按小孔速度流出去。如果倒得太快,桶满了,多余的水就溢出或排队失败。它的重点不是允许突发通过,而是让输出变平滑。

这两个算法都限制平均速率,但对突发流量的态度不同。令牌桶对短时突发更宽容,漏桶对下游更友好。

二、令牌桶的核心参数是速率和容量

令牌桶有两个关键参数:令牌生成速率 rate 和桶容量 capacity。假设 rate = 100/scapacity = 200,表示系统每秒生成 100 个令牌,最多攒 200 个。请求到来时,如果桶里有令牌,就消耗一个令牌放行;没有令牌就拒绝、排队或降级。

它的伪代码可以这样理解:

now = currentTime()
newTokens = (now - lastRefillTime) * rate
tokens = min(capacity, tokens + newTokens)
lastRefillTime = now

if tokens >= 1:
  tokens -= 1
  allow
else:
  reject

因为令牌可以累积,所以请求低谷后可以承接短时高峰。长期看,请求通过量不会超过令牌生成速率;短期看,最大突发量由桶容量决定。

三、漏桶的核心是固定输出速率

漏桶更强调把输入流量变成稳定输出。请求来了先进入队列或桶中,处理线程按固定速率取出执行。如果桶满了,新请求被拒绝或丢弃。

漏桶适合下游无法承受突发的场景。比如写入某个第三方接口,对方限制每秒 50 次,超了就封禁;或者数据库某个批处理任务必须匀速写入,不能瞬间冲击。漏桶可以把前端不均匀的请求变成后端稳定的处理节奏。

但漏桶会引入等待时间。如果请求突然增多,桶里的请求排队,用户可能感知延迟。因此漏桶要设置最大队列长度和最大等待时间,避免把系统变成无限排队。

四、令牌桶适合 API 限流,漏桶适合流量整形

开放 API 常用令牌桶。比如某用户每秒平均 100 次请求,允许短时 burst 到 200。这样用户程序偶尔并发一小波不会马上失败,但持续高压会被限制。令牌桶兼顾公平和体验。

漏桶更像流量整形。比如消息消费端从 MQ 拉到很多消息,但数据库每秒只能稳定写 1000 条,就可以漏桶式控制写入速率。它牺牲瞬时吞吐,换下游稳定。

当然,工程里两者可以组合。入口用令牌桶挡掉超额请求,下游用漏桶平滑写入,核心接口再加并发数限制,形成多层保护。

五、桶容量设置不当会出问题

令牌桶容量过大,会允许过大的突发流量瞬间进入系统,打爆下游;容量过小,会把正常业务小抖动也拒掉,用户体验差。容量通常要结合下游缓冲能力、线程池大小、P99 延迟和业务突发特征设置。

漏桶容量过大,会导致请求排队很久,用户等到超时还占用资源;容量过小,会频繁拒绝,削峰能力不足。漏桶要特别关注最大等待时间,不要只看队列长度。

一个常见误区是认为限流后请求排队越多越好。排队不是免费午餐,请求在队列里占内存、占连接、占用户耐心;排队时间超过业务可接受范围,不如快速失败。

六、分布式场景中的实现差异

单机令牌桶可以放在内存里,性能非常好。分布式令牌桶要多个节点共享额度,常见实现是 Redis Lua 原子脚本、集中式限流服务、网关统一限流、本地预分配令牌。共享额度越精确,中心依赖越重;越偏本地,误差越大但可用性更好。

漏桶在分布式场景里经常体现为队列削峰。所有请求进入 MQ,消费者按固定速率处理。这样天然实现平滑输出,但要处理消息堆积、过期、重复消费、优先级和死信。

面试时可以补充:算法只是模型,落地还要考虑原子性、时钟、中心组件可用性、网络开销和失败策略。

七、面试追问里的判断方法

如果面试官问“秒杀用令牌桶还是漏桶”,要先看目标。入口要挡住大量无效流量,可以用令牌桶或更严格的库存令牌;进入下单链路后,为了保护数据库和库存服务,可以用队列或漏桶式消费削峰。如果只是说“秒杀用令牌桶”会显得太单薄。

如果问“令牌桶为什么允许突发”,答案是令牌可以在低流量时累积,突发时一次性消耗存量令牌。突发上限由桶容量控制,平均速率由令牌生成速率控制。

如果问“漏桶有什么缺点”,重点说排队延迟、桶满丢弃、突发响应不够友好,以及要设置超时和最大队列长度。

八、常见误区与追问

这道题要紧扣「令牌桶与漏桶」本身回答,不能把它混成泛泛的流量控制套话。面试官通常不是只听定义,而是看你能不能把适用场景、关键流程、失败边界和工程取舍串起来,尤其要说明限流位置、算法窗口、阈值来源、拒绝策略、退避降级和观测指标。

回答层次要讲清的内容容易漏掉的边界
核心结论令牌桶允许一定突发,漏桶强制匀速流出;选择取决于业务能否接受突刺不要停在名词解释
流程机制定速生成令牌或入桶 -> 请求到达尝试获取 -> 有令牌则通过 -> 无令牌则拒绝或等待 -> 漏桶按固定速率流出 -> 监控桶深和拒绝率要说清触发点、状态变化、确认点和失败兜底
工程取舍令牌桶容量 100、生成速率 10/s,空闲 10 秒后可瞬间通过最多 100 个请求限流保护系统稳定性,但会牺牲一部分请求成功率或响应实时性
令牌桶与漏桶 面试拆解:
1. 定速生成令牌或入桶
2. 请求到达尝试获取
3. 有令牌则通过
4. 无令牌则拒绝或等待
5. 漏桶按固定速率流出
6. 监控桶深和拒绝率

记忆钩子:先给结论,再拆流程,再讲数字例子和失败边界;回答「令牌桶与漏桶」时要围绕题目问法收束,不要把相邻概念堆成一段没有重点的名词清单。

  • 误区:限流就是简单拒绝请求。 合格答案要区分放行、排队、快速失败、降级、退避和熔断,而不是只说“挡住流量”。
  • 误区:全局平均流量低就没有风险。 热点 key、单实例、单下游资源仍可能先被打满,所以要看局部水位。
  • 误区:限流阈值可以拍脑袋配置。 阈值要来自压测容量、依赖水位、错误率、P99 延迟和业务优先级。
  • 追问:限流应该放在哪里? 入口网关、服务内部、客户端和下游资源侧可以分层配置,分别保护不同边界。
  • 追问:触发限流后怎么处理? 核心写请求可排队,非核心读请求可降级,用户侧要给明确失败或稍后重试。
  • 追问:如何验证流控策略有效? 看 QPS、并发、延迟、拒绝率、队列长度、下游错误率和恢复时间。

九、加强记忆

令牌桶记住“按速率发通行证,攒下来的令牌允许突发”;漏桶记住“请求先进桶,再匀速流出,保护下游平稳”。令牌桶偏 API 限流和 burst 友好,漏桶偏流量整形和削峰。真正落地时,算法参数和失败策略比算法名字更重要。