对某些资源要控制访问次数,通常的思路统计时间段访问达到限制次数,这种时段是固定的,好比说1分钟的时间段,有多是这样的: java
12:01至12:02
12:02至12:03
12:03至12:04
....
这样统计出来的数据,严格来讲是不太正确的。其实,我所理解时间段是没有固定的开始和结束点,这两点应该是随着时间不断前进的。可是,基于这种时间段实现很是困难。不过能够把大的时间段分割成小的时间段, 这样统计出来的数据相对正确。代码以下: post
@Test public void testCounter(){ while(true){ accessControl("post/message",1000, 10 , 200);//1000ms访问次数不能超过200次 } } /** * precision越高越精确 * * 单位 毫秒 * @param path * @param interval 时间段 * @param precision 精确度 * @param control 最大访问次数 */ private void accessControl(String path , long interval , long precision , int control ){ long now = System.currentTimeMillis() ; long pow = (now / precision) * precision ; String key = path+"_"+pow ; boolean keyExists = client.keyExists(key ) ; if(keyExists){ client.incr(key, 1l); }else{ Date expire = new Date(now + interval); client.set(key , "1" , expire ) ; } int keySize = (int)(interval/precision) ; String [] keys = new String[keySize] ; for(int i = 1 ; i <= keySize ; i++ ){ keys[i-1] = path+"_"+( pow - i * precision) ; } Map<String, Object> multi = client.getMulti(keys) ; int num = 0 ; for(Object value : multi.values() ){ if(value != null ){ num += Integer.valueOf(String.valueOf(value)) ; } } if(control <= num ){ throw new RuntimeException("访问次数过多"); } }