← 中文资源

简体中文版本

实现滑动窗口限流

使用滑动窗口或令牌桶并共享状态,使限流在多实例间准确,且在固定窗口边界公平。

阅读英文原文

概述

固定窗口限流在边界处允许两倍突发,且每实例各算一份会放大限额。滑动窗口或令牌桶配合共享状态,可让限额平滑且全局一致,代价是每次请求多一次共享存储往返。

关键步骤

  1. 选择滑动窗口或令牌桶,而非固定窗口。
  2. 以客户端标识与路由为键,在共享存储中保存计数或令牌。
  3. 用 Lua 脚本或原子操作读写计数。
  4. 超限时返回 429 与 Retry-After 及限额头。

验证

  • 边界处不会出现两倍突发。
  • 多实例共享同一限额。
  • 并发请求不会超出限额。
  • 客户端能按 Retry-After 退避。

注意事项

  • 共享存储限流每请求增加一次往返,自身可能成为瓶颈。
  • 分区下分布式限流是近似值,需明确其失败模式。

适用范围

本条目围绕「实现滑动窗口限流」给出可复制的步骤、验证方式与常见问题,适合需要按此流程落地的工程团队。执行时请结合自身上下文调整命令与阈值,并在变更前后留存证据,便于后续复核与回滚。

const allowed = await redis.eval(TOKEN_BUCKET_LUA, 1, `rl:${clientId}`, now, rate, capacity);
if (!allowed) {
  res.setHeader('Retry-After', '1');
  return res.status(429).json({ error: { code: 'rate_limited' } });
}