事出
由于我的博客上线了,因为我的博客有评论之后会判断是不是主评论,如果是主评论就会给我发送邮件通知,如果是子评论会给收到评论的人发送邮件通知,但是这就有可能会有人恶意的刷评论会导致我的mq阻塞甚至挂掉,给本身配置不是很高的服务器增加压力。
想法
我们可以限制单位时间内用户发送评论的次数,然后我就写了一个限流的方法,使用的是滑动窗口和redis中的zset
思路
前提
其实整体的思路不难,懂滑动窗口的应该不难理解,我一步一步来讲。
在我这个项目中有一个
这个canAccess方法只需要把你要根据什么条件区分,然后限制在多少时间内,只能操作几次就可以了。
内部分析
定义一个公共的前缀
我们先看一下这个方法的参数,我的项目中是使用接收邮件的地址拼接到前缀的后边做的key,然后我们先统计一下这个这个key中有多少个value如果超过了我们规定的那么就返回false,如果没有到我们能接受的最大请求数呢,那么就会进入下边这个方法了
计数增长
这个方法呢说他每句话都是干啥的,打多少人都知道,但是其中的细节就需要好好想一下了,我就按照大家不懂滑动窗口来讲了
我先讲一下这个方法里的每个语句是干啥的然后再说思路
首先我们得到当前时间戳,然后得到窗口开启时间,为了提高效率,我们使用单例模式,然后进来之后先把所有的过期值进行清空,然后把当前的时间戳添加进去,然后更新这个key的过期时间。
核心思想
我们在请求第一次的时候情况是这样的
他会清空在8.05之前所有的value但是此时是没有的,所有没关系,后边把这个8.15的时间戳插入进去。
第二次我们在8.20的时候请求
我们第二次请求的时候是在8.20分此时会将8.10分之前的值进行清空
两种情况
现在我们先模仿一下第四次请求超过十分钟的情况
此时我们第四次如果在十分钟之外请求的话,我们第四次来了之后,会判断当前里边有多少个值,此时是三个,会相等,然后把过期的值清空,这个时候我们重新获得一下里边的个数然后就行判断就行
第四次请求没有超过十分钟的情况
此时在10分钟之内已经超过了第四次是在8:24他存入值之前zset里边的值已经等于3了那么我们此时先清空一下过期的值,再判断然而还是超过了,所以我们就不能够请求了