- URL: https://smudge.ai/blog/ratelimit-algorithms
- Added At: 2025-05-09 15:39:33
速率限制用于防止服务过载,确保公平性与稳定性。主要算法包括:固定窗口法(简单但允许突发流量)、滑动窗口法(平滑流量但资源消耗高)、令牌桶算法(支持突发且控制长期平均速率)。实现时需使用持久化存储(如Redis)、设计容错机制(链路失败启用开放策略)、选择用户标识(IP/设备指纹等),并返回429状态码及剩余配额。建议根据场景选择:简单场景用固定窗口,高并发场景选滑动窗口近似算法,需平衡突发与长期流量则用令牌桶。
文章总结:
速率限制的必要性
防止服务过载(如聊天中的垃圾消息、暴力破解攻击、API资源垄断),通过限制单位时间内请求量,确保公平性与稳定性。
三种核心算法
-
固定窗口法(Fixed Window)
- 机制:预设时间窗口内允许固定请求数,窗口结束时重置计数器。
- 优点:简单易实现,窗口起始时间固定(如GitHub每小时限5000次API调用)。
- 缺点:允许窗口结束前的突发请求(达2倍限额)。时区处理复杂(需同步用户时区,但可能导致滥用)。
- 改进:窗口起始时间与用户首请求绑定,但需显示剩余等待时间。
-
滑动窗口法(Sliding Window)
- 机制:按时间比例动态计算窗口内请求数,避免突发流量。
- 优点:流量平滑,适合高并发场景(如Cloudflare的近似算法)。
- 缺点:需存储所有请求时间戳,资源消耗高。实际使用近似算法(如“浮动窗口”加权计算历史和当前窗口)。
-
令牌桶(Token Bucket)
- 机制:桶内按固定速率填充令牌,每请求消耗1令牌,无令牌时阻断。
- 优点:支持突发流量,区分瞬时峰值与长期速率(如Twitch聊天每4秒补1令牌,限1消息/4秒)。
- 应用案例:Stripe每秒补2000令牌(500容量桶,限100/s长期平均);OpenAI每日补200令牌。
关键注意事项
- 数据存储:使用持久化存储(如Redis)而非内存,应对横向扩展或服务重启。
- 容错设计:链路失败时“启用开放”(允许所有请求,避免完全阻断)。
- 键选择:按用户ID/API Key/IP等唯一标识限流。未认证用户可通过IP或设备指纹。
- 错误反馈:返回429状态码,提供剩余配额等元数据(如GitHub和OpenAI的响应头)。
算法选择建议
- 固定窗口:适合简单场景或需严格起始时间(如日历日限流)。
- 滑动窗口近似算法:高流量场景的平滑控制(如Cloudflare实现)。
- 令牌桶:需支持突发流量同时控制长期平均速率(如聊天应用或API限流)。