速率限制(限制在一个时间窗口内允许多少个请求/操作)是常见的 Redis 用例——Redis 的快速原子计数器和 TTL 使其成为理想选择。存在多种算法(固定窗口、滑动窗口、令牌桶),各有权衡。
固定窗口(最简单)
() {
key = ;
count = redis.(key);
(count === ) redis.(key, windowSec);
count <= limit;
}
速率限制(限制在一个时间窗口内允许多少个请求/操作)是常见的 Redis 用例——Redis 的快速原子计数器和 TTL 使其成为理想选择。存在多种算法(固定窗口、滑动窗口、令牌桶),各有权衡。
() {
key = ;
count = redis.(key);
(count === ) redis.(key, windowSec);
count <= limit;
}
固定窗口方法:每个(用户、时间窗口)对应一个原子计数器,带有 TTL——每个请求时增加,超过限制时拒绝。利用原子 INCR 和自动过期,简单高效。
✗ Limitation: bursts at window boundaries (2x limit possible across two adjacent windows)
SLIDING WINDOW → tracks requests over a rolling time period (no boundary bursts)
→ often uses a SORTED SET: add each request with a timestamp score,
remove old entries (ZREMRANGEBYSCORE), count remaining (ZCARD)
✓ More accurate/smooth ✗ More memory and complexity
TOKEN BUCKET → tokens refill at a steady rate; each request consumes a token
→ allows bursts (up to the bucket size) while limiting the average rate
→ often implemented with a Lua SCRIPT for atomic check-and-consume
✓ ATOMIC counters (INCR) → correct under concurrency, no race conditions
✓ Fast (in-memory) → minimal latency added to each request
✓ TTL → automatic window cleanup (no manual expiry management)
✓ SHARED across servers → distributed rate limiting (all app servers use one Redis)
→ Redis is the standard tool for distributed rate limiting.
使用 Redis 实现速率限制是常见的实际用例,因此理解它是宝贵的知识——速率限制(保护 API 和服务免受滥用、确保公平使用、防止过载)几乎是普遍需要,而 Redis 是标准工具。
理解 Redis 为何理想 是关键:它的 原子计数器(INCR)使速率计数在并发下正确(无竞态条件/丢失计数),它的 速度(内存中)为每个请求增加最少延迟,TTL 自动处理窗口清理,更重要的是它 跨服务器共享 ——实现 分布式速率限制,其中所有应用服务器执行一个一致的限制(在多服务器部署中至关重要,其中每服务器内存中的限制不适用)。
理解 算法及其权衡让你能适当选择:固定窗口(最简单——每个时间窗口一个原子计数器,带 TTL,但允许边界突发),滑动窗口(使用带时间戳的请求排序集,更平滑更准确,但内存成本较高),和 令牌桶(允许受控的突发同时限制平均速率,通常通过 Lua 脚本实现原子性)。
知道如何实现这些(特别是简单常见的固定窗口模式,使用 INCR + EXPIRE)是实用、可应用的技能。
由于速率限制是保护服务的常见需求,而 Redis(具有原子计数器、速度、TTL 和跨服务器共享)是分布式速率限制的标准、理想工具,理解如何使用 Redis 实现它——算法、权衡及 Redis 为何完全适合——是构建健壮、受保护服务的宝贵、经常应用的知识,也是 Redis 在缓存之外最常见的实际应用之一。