1. 简介
Springboot集成Redisson默认的限流器为令牌桶型限流器,底层是通过lua脚本去实现的。
通过lua脚本我们可以去实现一个滑动窗口限流器,利用ZSET格式数据就可以轻松实现。
springboot集成Redisson就不做讲解,可以参考:springboot集成redisson
2. 滑动窗口lua脚本讲解
lua
-- 移除时间窗口之外的数据,通过ZSET自带的排序score可以轻松做到
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, tonumber(ARGV[2]) - tonumber(ARGV[3]));
-- 判断当前窗口是否达到限流限制
if (redis.call('ZCARD', KEYS[1]) >= tonumber(ARGV[1])) then
return nil;
end;
-- 添加对应的数据
redis.call('ZADD', KEYS[1], ARGV[2], ARGV[2]);
-- 过期时间更新,防止key一直占用
redis.call('pexpire', KEYS[1], ARGV[3]);
return true;
3. 调用
java
/**
* 滑动窗口限流
* @param key 限流key
* @param threshold 阈值
* @param interval 时间间隔
* @param unit 单位
* @return true-通过 false-限制
*/
public static boolean rateLimiterSlidingWindow(String key, long threshold, long interval, TimeUnit unit) {
RScript rScript = redissonClient.getScript();
long now = System.currentTimeMillis();
long intervalMs = TimeUnit.MILLISECONDS.convert(interval, unit);
return rScript.eval(RScript.Mode.READ_WRITE, slidingWindowScript, RScript.ReturnType.BOOLEAN,
Collections.singletonList(key), threshold, now, intervalMs);
}