rate limiting参数配置与中间件缓存同步 - 第1节

1.1 什么是限流

限流(Rate Limiting)是一种控制资源访问频率或并发量的技术手段。它通过限制在特定时间窗口内允许通过的请求数量,防止系统被突发流量冲垮,确保后端服务的稳定性和公平性。

限流的核心目标可以概括为三点:

  • 保护系统资源:防止数据库、CPU、内存等资源被过度消耗。
  • 保障服务质量:避免因个别用户过度占用资源而影响其他用户的正常使用。
  • 成本控制:在云服务或按量计费场景下,限制不必要的资源开销。
关键认知:限流不是拒绝用户,而是有策略地延迟或降级请求,让系统在过载时仍能提供可预期的服务。

1.2 为什么需要限流

在分布式系统和微服务架构中,限流是保障系统韧性的第一道防线。以下场景如果没有限流,系统极易发生雪崩:

场景 风险描述 限流效果
突发流量(秒杀、热点事件) 瞬间请求量达到正常值的 10~100 倍,服务直接 OOM 或连接池耗尽 平滑流量峰值,保证核心交易链路可用
恶意爬虫 / DDoS 攻击 大量无效请求占用带宽和计算资源,正常用户无法访问 快速识别并拦截异常高频请求
上游服务故障重试风暴 客户端重试 + 负载均衡重试导致请求量指数级放大 限制重试频率,防止级联故障
资源瓶颈(数据库连接、API 配额) 超过数据库最大连接数或第三方 API 调用配额 提前拒绝请求,避免超时和报错
常见误区:限流不能替代容量规划。限流是“兜底”手段,合理的容量评估和弹性伸缩才是根本。

1.3 常见限流算法简介

不同的限流算法在精度、内存开销和突发处理能力上各有优劣。下面介绍三种最核心的算法:令牌桶、漏桶和滑动窗口。

1.3.1 令牌桶算法(Token Bucket)

令牌桶以固定速率向桶中放入令牌,每个请求需要消耗一个令牌才能被处理。桶有容量上限,允许一定程度的突发流量。

  • 核心参数:rate(令牌生成速率)、capacity(桶容量)
  • 优点:允许突发,实现简单,性能高
  • 缺点:短期突发可能超过实际处理能力
  • 典型应用:Guava RateLimiter、Nginx ngx_http_limit_req_module
令牌桶算法流程 令牌生成器 rate 个/秒 令牌桶 容量 capacity 当前令牌数 请求 处理 拒绝 放入令牌 消耗令牌 有令牌 无令牌

1.3.2 漏桶算法(Leaky Bucket)

漏桶将请求放入一个固定容量的桶中,然后以恒定速率从桶底“漏出”请求进行处理。桶满时新请求被丢弃。

  • 核心参数:leak_rate(漏出速率)、bucket_size(桶容量)
  • 优点:输出流量绝对平滑,适合流量整形
  • 缺点:无法应对突发流量,所有请求必须排队等待
  • 典型应用:网络 QoS、流量整形设备
漏桶算法流程 请求 漏桶 容量 bucket_size 排队请求数 恒定速率处理 拒绝 流入 漏出 桶满丢弃

1.3.3 滑动窗口算法(Sliding Window)

滑动窗口将时间划分为多个小格子,维护一个固定大小的窗口,统计窗口内所有格子的请求总数。窗口随时间向前滑动,丢弃过期格子数据。

  • 核心参数:window_size(窗口大小,如 1s)、threshold(阈值)
  • 优点:相比固定窗口,能有效避免“临界突变”问题,精度可控
  • 缺点:需要存储窗口内每个格子的计数,内存开销略高
  • 典型应用:Redis 限流、API Gateway 限流
滑动窗口算法示意(窗口大小 1s,格子 200ms) T T+1s 200ms 200ms 200ms 200ms ... 当前滑动窗口(1s) 滑动方向 窗口内请求总数 = 格子1 + 格子2 + 格子3 + 格子4 ≤ 阈值

1.4 三种算法对比

特性 令牌桶 漏桶 滑动窗口
突发处理 允许突发(桶容量内) 不允许突发 允许突发(窗口内)
输出流量 可能不平滑 绝对平滑 取决于窗口粒度
内存开销 低(仅维护计数器) 低(仅维护队列长度) 中(需存储格子计数)
精度 较高 高 高(格子越细精度越高)
实现复杂度 简单 简单 中等
典型场景 API 限流、微服务限流 流量整形、网络 QoS 分布式限流、网关限流
选型建议:
• 需要允许突发流量且实现简单 → 令牌桶
• 需要绝对平滑的输出流量 → 漏桶
• 需要高精度且能接受一定内存开销 → 滑动窗口
• 实际生产环境中,令牌桶和滑动窗口的组合使用非常常见。