對某些資源要控制訪問次數,通常的思路統計時間段訪問達到限制次數,這種時段是固定的,好比說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("訪問次數過多"); } }