咱们知道当网站的访问量忽然很大的时候确定会对服务器形成影响,甚至没法访问,若是是正常的访问那么很好说明业务量增大能够考虑系统的扩展,可是若是是搜索引擎爬虫频繁访问或是一些恶意访问,那这时候咱们就应该限制这些访问的访问次数。redis恰好能够解决这个问题java
限制每一个用户每分钟最多只能访问100个页面。实现思路:key使用有"rate.limiting:IP",value使用数值,用户每次访问将value的值经过INCR命令自增1.若是自增后的值是1同时设置过时时间为1分钟。这样用户每次访问的时候都读取该键的值,若是超过了100就代表该用户的访问频率超过了限制,须要提示用户稍后访问。且该键每分钟会自动被删除。因此下一分钟又会从新计算,也就达到了限制访问频率的目的。
redis
代码逻辑:算法
String key = "rage.limiting:"+ip; // 判断key是否存在 int flag = exists(key);// key rate.limiting:192.168.88.60 if(flag == 1){ // key 存在 自增1 int count = incr(key); if(count > 100){ // 超过限制 log.info("访问频率超过了限制,请稍后重试"); return ; } }else{ // key 不存在 multi(); // 开启事务 incr(key); // key不存在自增1 值为1 expire(key,60); // 设置过时时间 exec(); // 提交事务 }
实现方式一其实还有个问题,好比若是用户第一分钟的访问了99次,前面58秒访问了9次,后面1秒访问了90次,而后用户后一秒也访问了99次,然后一分钟的第一秒访问了90次,后面的58秒访问了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); } }