我们提供安全,免费的手游软件下载!
滑动窗口限流是一种热门的限流算法,通过维护固定大小的窗口,在设定的时间内限制通过的请求数量不超过指定的阈值。该算法主要包括以下步骤:
滑动窗口限流算法是有效控制系统请求流量、避免系统被大量请求压垮的方式。由于其简单高效的特性,该算法被广泛应用于接口限流、流量控制等场景。然而,需要注意的是,滑动窗口限流算法无法完全解决突发请求问题,因此在实际应用中可能需要与其他策略综合考虑。
/**
* 滑动窗口限流. 需要注意的是,我们要定期清楚过期的key,否则会导致内存泄漏,可以使用ZREMRANGEBYSCORE方法实现.
* @param key 限流的key
* @param timeWindow 单位时间,秒
* @param limit 窗口大小,单位时间最大容许的令牌数
* @param runnable 成功后的回调方法
*/
public void slidingWindow(String key, int timeWindow, int limit, Runnable runnable) {
Long currentTime = System.currentTimeMillis();
if (redisTemplate.hasKey(key)) {
Long intervalTime = timeWindow * 1000L;
Long from = currentTime - intervalTime;
Integer count = redisTemplate.opsForZSet().rangeByScore(key, from, currentTime).size();
if (count != null && count >= limit) {
throw new RedisLimitException("每" + timeWindow + "秒最多只能访问" + limit + "次.");
}
log.info("from key:{}~{},current count:{}", from, currentTime, count);
}
redisTemplate.opsForZSet().add(key, UUID.randomUUID().toString(), currentTime);
Optional.ofNullable(runnable).ifPresent(o -> o.run());
}
上述代码基于时间戳作为主要窗口依据,实现了基于滑动窗口的限流逻辑。由于zset的数据量随时间增长,我们需定期根据score来清理它。
/**
* 清理昨天的zset元素,应该写成任务调度,每天执行一次,清除过期的zset元素.
* @param key
*/
public void delByYesterday(String key) {
Instant currentInstant = Instant.now();
Instant oneDayAgoInstant = currentInstant.minusSeconds(86400);
long oneDayAgoTimeMillis = oneDayAgoInstant.toEpochMilli();
redisTemplate.opsForZSet().removeRangeByScore(key, 0, oneDayAgoTimeMillis);
}
事实上,上述逻辑可以用其他语言实现,例如通过go语言实现相关逻辑,并可在MSE网关上实现限流功能。
热门资讯