访问次数控制实现思路

对某些资源要控制访问次数,通常的思路统计时间段访问达到限制次数,这种时段是固定的,好比说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("访问次数过多");
		}
		
		
	}
相关文章
相关标签/搜索