如何基于Redis实现滑动窗口限流
·
滑动窗口限流是一种流量控制策略,通过维护一个滑动时间窗口来限制单位时间内允许的操作数量。该策略能平滑控制流量,相比固定速率限制更加灵活,能有效应对突发流量而不浪费系统资源。
基于Redis的滑动窗口限流实现方案
原理说明
- 利用时间窗口记录请求时间戳
- 统计窗口内的请求总数来判断是否超出限制
- 自动清理窗口外的历史数据
Redis实现方案 推荐使用ZSET数据结构
- key:限流的资源标识(如接口名)
- score:请求时间戳
- member:请求唯一标识(建议使用UUID/MD5避免并发冲突)

示例
以登录接口1分钟100次调用为例,实现步骤如下:
- 记录当前请求时间戳
- 清理60秒前的历史数据
- 统计当前窗口内请求数
- 未超限则记录本次请求
基础实现代码示例:
import redis.clients.jedis.Jedis;
public class SlidingWindowRateLimiter {
private Jedis jedis;
private String key;
private int limit;
public boolean allowRequest(String key) {
long currentTime = System.currentTimeMillis();
long windowStart = currentTime - 60 * 1000;
jedis.zremrangeByScore(key, "-inf", String.valueOf(windowStart));
long currentRequests = jedis.zcard(key);
if (currentRequests < limit) {
jedis.zadd(key, currentTime, String.valueOf(currentTime));
return true;
}
return false;
}
}
原子性优化方案(使用Lua脚本):
import redis.clients.jedis.Jedis;
public class SlidingWindowRateLimiter {
private Jedis jedis;
private String key;
private int limit;
public boolean allowRequest(String key) {
long currentTime = System.currentTimeMillis();
String luaScript = "local window_start = ARGV[1] - 60000\n" +
"redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', window_start)\n" +
"local current_requests = redis.call('ZCARD', KEYS[1])\n" +
"if current_requests < tonumber(ARGV[2]) then\n" +
" redis.call('ZADD', KEYS[1], ARGV[1], ARGV[1])\n" +
" return 1\n" +
"else\n" +
" return 0\n" +
"end";
Object result = jedis.eval(luaScript, 1, key, String.valueOf(currentTime), String.valueOf(limit));
return (Long) result == 1;
}
}
相关知识
Redis命令说明
ZREMRANGEBYSCORE:移除指定分数区间的成员ZCARD:获取有序集合成员数量-inf表示负无穷,用于清理所有历史数据
基于Redisson实现限流
在 Redisson框架中,已经给我们提供了一个限流器——RRateLimiter,不过他并不是滑动窗口,而是一个令牌桶的算法。具体的可以参考:Redisson分布式限流器RRateLimiter原理解析
使用方式如下:
public Boolean tryAcquire(String key, int limit, int windowSize) {
RRateLimiter rRateLimiter = redissonClient.getRateLimiter(LIMIT_KEY_PREFIX + key);
if (!rRateLimiter.isExists()) {
rRateLimiter.trySetRate(RateType.OVERALL, limit, windowSize, RateIntervalUnit.SECONDS);
}
return rRateLimiter.tryAcquire();
}
更多推荐
所有评论(0)