如果网站收到恶意攻击,网站访问频率可能在某个时间段特别高可能,影响网站性能,严重还能能导致往网站直接崩溃;网站的访问频率限制可以解决这个问题,

Redis实现限制访问频率

1:实现访问:

例如限制每个用户在一段事件内只能访问一定数量的次数如;一分钟只能访问100次,思路:key可以使用 "rete.limiting:ip",value 使用数值,用户每次访问将通过INCR命令自增1,如果自增后的值是1同时设置过期时间为1分钟,这样用户每次访问的时候都读取该键值,如果超过了100次,就表名访问超过了限制,需要提醒用户稍后访问,且该键值每分钟会自动删除,所以下一分钟有会重新计算,这样就达到了范文频率的目的。

相关代码:

String key="rege.limiting:"+ip;
	//判断key是否存在
	int flag=exits(key);//key rate.limiting:192.162.177.128
	if(flag==1){
		//key 存在 自增
		ing count=incr(key);
		if(count>100){
			//超时限制
			log.info("访问频率超过了限制,稍后重试");
			return ;
		}
	}else{
		multi();//开启事务;
		incr(key);//key不存在自增1,值为1;
		expire(key,60);//设置过期时间
		exec();//事物提交
	}
实现方式二:

实现一些问题的时候还是有问题的,例如用户第一分钟的访问了99次,前面1秒访问了90次,然后用户后一秒访问而来99 次,然后下一分钟的第一秒有访问了90次,再后面的59秒访问了9次,这样上面的算法就是会有漏洞的:

解决方法:将上面案例中的100次调整为10次便于在次场景中描述,要精确的保证同一用户每分钟最多访问10次,需要将用户访问的事件记录下来,因此对每个用户我们使用List列表类型的键来记录他最近10次的访问时间,一旦键中元素超过了10个,就判断最早元素距离现在元素是否超过1分钟,如果表示用户最近1分钟访问次数超过了10次,就提醒稍后访问,如果不是就将现在的时间加入到队列中,同时将最早的元素删除。

代码:

String key = "rate.limiting:"+IP;
int listLength = llen(key);
if(listLength < 10){
	lpush(key,new());
}else{
	long time = lindex(key,-1);
	if(now()-time < 60){
		log.info("访问频率超过了限制,请稍后再试");
	}else{
		lpush(key,now);
		ltrim(key,0,9);
	}
}