时间窗口算法
又名滑动时间算法,所谓的滑动时间算法指的是以当前时间为截止时间,往前取一定的时间,比如取60s的时间,在这60s时间内最大的访问数为100。此时算法的执行逻辑为,先清除这60s 之前的所有请求记录,再计算当前集合内请求数是否大于设定的最大请求数100,如果大于100则执行限流拒绝策略,否则插入本次请求记录并返回可以正常执行的标识给客户端。
滑动时间窗口如下图所示:
其中每一个小格子代表10s,被红色虚线包围的时间段则为需要判断的时间间隔,比如60s允许100次请求,那么红色虚线部分则为60s。
如何实现?
借助Redis的有序集合ZSet来实现时间窗口算法限流,实现的过程是:
第一步:先使用ZSet的key存储限流的ID,score用来存储请求的时间。
第二步:每次有请求访问来了之后,先清空之前时间窗口的访问量,统计目前时间窗口的个数与最大允许访问量对比。
第三步:如果大于等于最大访问量则返回 false 执行限流操策略,负责允许执行业务逻辑,并且在 ZSet 中添加一条有效的访问记录。
代码实操
我们借助 Jedis 包来操作 Redis,首先在pom.xml中添加Jedis的jar包:
redis.clients jedis 3.3.0
具体的 Java代码如下:
package com.example.demo;
import redis.clients.jedis.Jedis;
/** * 6种限流方法之服务端时间窗口算法 * * @author www.jiagou1216.com */public class RedisLimit { /** * Redis 操作客户端 */ static Jedis jedis = new Jedis("127.0.0.1", 6379);
public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 100; i++) { boolean res = isPeriodLimiting("jiagou1216.com", 3, 10); if (res) { System.out.println("正常访问【https://www.jiagou1216.com】:" + i); } else { System.out.println("限流访问【https://www.jiagou1216.com】:" + i); } } // 休眠 4s Thread.sleep(4000); // 超过最大执行时间之后,再从发起请求 boolean res = isPeriodLimiting("jiagou1216.com", 3, 10); if (res) { System.out.println("休眠后,正常执行请求"); } else { System.out.println("休眠后,被限流"); } }
/** * 限流方法(滑动时间算法/时间窗口算法) * * @param key 限流标识 * @param period 限流时间范围(单位:秒) * @param maxCount 最大运行访问次数 * @return 是否限流 */ private static boolean isPeriodLimiting(String key, int period, int maxCount) { // 当前时间戳 long nowTs = System.currentTimeMillis(); // 删除非时间段内的请求数据(清除老访问数据,比如 period=60 时,标识清除 60s 以前的请求记录) jedis.zremrangeByScore(key, 0, nowTs - period * 1000); // 当前请求次数 long currCount = jedis.zcard(key); if (currCount >= maxCount) { // 超过最大请求次数,执行限流 return false; } // 未达到最大请求数,正常执行业务,请求记录 +1 jedis.zadd(key, nowTs, "" + nowTs); return true; }}
运行main方法
这种方式有两个缺点:
1)使用 ZSet 存储有每次的访问记录,如果数据量比较大时会占用大量的空间,比如60s允许100W访问时;
2)此代码的执行非原子操作,先判断后增加,中间空隙可穿插其他业务逻辑的执行,有可能导致结果不准确。
架构师小跟班,技术类综合网站,是本站长出于个人爱好,搭建的纯公益性质的博客网站,旨在为各位站长,程序员、学生提供免费的开发软件,视频教程,系统源码,网站模板等。
本站做过多次优化,解决了网站打开慢,谷歌浏览器报不安全提示等问题。
本站每周会有多次更新,内容完全免费,尤其是系统源码、毕业设计、视频教程等,没有任何套路,请大胆收藏和推荐。
但请粉丝们注意:
本站部分内容是站长从网络搜集所得,没有著作权,请勿用于商业用途,请下载后24小时内删除。谢谢合作!
领取专属 10元无门槛券
私享最新 技术干货