storm中的RotatingCache技術

一,基本的原理

  偶遇storm中的rotatecache算法,特地研究一下。

  核心:

  1,是採用了鏈表來組織多個桶來存儲數據;

   2,插入數據時直接插入到第一個桶中,清除到其它桶中的同key值的數據;

  3,刪除數據移除所有桶中的數據(此處需要遍歷)

  4,回收數據的時候,採用了非常巧妙的方式,在鏈表頭新加一個桶,刪除尾部的桶刪除掉,如果帶回調,調用一下回調函數。

二,代碼

  1,涉及到三個文件,rotatingmap本身代碼

/************************************************************************* 
> File Name: rotatingmap.java
> Author:zhangtx 
> Mail: [email protected]  
> Created Time: 2016年4月12日 星期四 13時12分14秒 
************************************************************************/ 

package org.jinher.research.RotatingMap;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

public class RotatingMap<K,V> {
	
	private static final int DEFAULT_NUM_BUCKETS=3;
	
	/*
	 * rotate的回調接口口
	 * */
	public static interface ExpiredCallback<K,V>{
		public void expire(K key,V val);
	}
	
	private LinkedList<HashMap<K,V>> _buckets;
	
	private ExpiredCallback _callback;
	
	public RotatingMap(int numBuckets,ExpiredCallback<K,V> callback)
	{
		if (numBuckets<2)
		{
			throw new IllegalArgumentException("numBuckets must be >=2");
		}
		_buckets=new LinkedList<HashMap<K,V>>();
		for(int i=0;i<numBuckets;i++)
		{
			_buckets.add(new HashMap<K,V>());
		}
		_callback=callback;
	}
	public RotatingMap(ExpiredCallback<K,V> callback)
	{
		this(DEFAULT_NUM_BUCKETS,callback);
	}
	public RotatingMap(int numBuckets)
	{
		this(numBuckets,null);
	}
	
	public Map<K,V> rotate()
	{
		Map<K,V> dead=_buckets.removeLast();
		_buckets.addFirst(new HashMap<K,V>());
		if(_callback!=null)
		{
			for(Entry<K,V> entry:dead.entrySet())
			{
				_callback.expire(entry.getKey(),entry.getValue());
			}
		}
		return dead;
	}
	public boolean containsKey(K key)
	{
		for(HashMap<K,V> bucket:_buckets)
		{
			if (bucket.containsKey(key))
			{
				return true;
			}
		}
		return false;
	}
	public V get(K key)
	{
		for(HashMap<K,V> bucket:_buckets)
		{
			if(bucket.containsKey(key))
			{
				return bucket.get(key);
			}
		}
		return null;
	}
	/*存儲數據*/
	public void put(K key,V value)
	{
		Iterator<HashMap<K,V>> it=_buckets.iterator();
		/*put to the first bucket*/
		HashMap<K,V> bucket=it.next();
		bucket.put(key, value);
		/*remove key from others bucket*/
		while(it.hasNext())
		{
			bucket=it.next();
			bucket.remove(key);
		}
	}
	
	public Object remove(K key)
	{
		/*移除數據*/
		for(HashMap<K,V> bucket:_buckets)
		{
			if(bucket.containsKey(key))
			{
				return bucket.remove(key);
			}
		}
		return null;
	}
	
	public int size()
	{
		int size=0;
		/*計算各個桶中數據的個數之和*/
		for(HashMap<K,V> bucket:_buckets)
		{
			size+=bucket.size();
		}
		return size;
	}

}
2,回調接口實現代碼

/************************************************************************* 
> File Name: rotatingmap.java
> Author:zhangtx 
> Mail: [email protected]  
> Created Time: 2016年4月12日 星期四 13時12分14秒 
************************************************************************/ 

package org.jinher.research.RotatingMap;

public class EventHandler<K,V> implements RotatingMap.ExpiredCallback<K, V> {

	public void expire(K key, V val) {
		// TODO Auto-generated method stub
		System.out.println("key="+key+",val="+val);
	}
}
3,測試代碼

  

/************************************************************************* 
> File Name: rotatingmap.java
> Author:zhangtx 
> Mail: [email protected]  
> Created Time: 2016年4月12日 星期四 13時12分14秒 
************************************************************************/ 

package org.jinher.research.RotatingMap;

import java.text.SimpleDateFormat;
import java.util.Date;

public class RotatingMapStarter 
{
	RotatingMap<String,String> m_rotatingMap=null;
	RotatingMap.ExpiredCallback<String, String> m_eventHandler=null;
	long m_lastRotate=System.currentTimeMillis();
	long m_rotateTime;
	
	public RotatingMapStarter(int n,int rotateTime)
	{
		m_eventHandler=new EventHandler<String,String>();
		m_rotatingMap=new RotatingMap<String,String>(4,m_eventHandler);
		m_lastRotate=System.currentTimeMillis();
		m_rotateTime=1000L*rotateTime;
	}
	public RotatingMap<String,String> getRotatingMap()
	{
		return m_rotatingMap;
	}
	public void setRotatingMap(RotatingMap<String,String> rotatingMap)
	{
		this.m_rotatingMap=rotatingMap;
	}
	public void startConnMonitor()
	{
		Thread thread=new Thread("Server Monitor")
		{
			public void run()
			{
				while(true)
				{
					runcore();
				}
			}
			public void runcore()
			{		
				try
				{
					Thread.currentThread().sleep(1000);
				}
				catch(InterruptedException e)
				{
					e.printStackTrace();
				}
				long now=System.currentTimeMillis();
				if(now-m_lastRotate>m_rotateTime)
				{
					m_rotatingMap.rotate();
					m_lastRotate=now;
				}
				else	
				{
					SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					System.out.println(df.format(new Date(now)));
				}
			}
		};
		thread.start();
	}
	 public static void main(String[] args)  
	 {  
	      RotatingMapStarter rotatingMapStarter = new RotatingMapStarter(4, 10);  
	      
	      rotatingMapStarter.startConnMonitor();  
	      
	      String value = "zhang";  
	      String key = "1";  
	      rotatingMapStarter.getRotatingMap().put(key, value);
	      
	      System.out.println("key="+key+",value="+rotatingMapStarter.getRotatingMap().get(key));
	      
	      String value1 = "tianxiang";  
	      String key1 = "2";  
	      rotatingMapStarter.getRotatingMap().put(key1, value1);
	      System.out.println("key="+key1+",value="+rotatingMapStarter.getRotatingMap().get(key1));
	      try {
			Thread.currentThread().sleep(100000000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	 } 

}

三,結果


key=1,value=zhang
key=2,value=tianxiang
2016-04-12 14:48:48
2016-04-12 14:48:50
2016-04-12 14:48:51
2016-04-12 14:48:52
2016-04-12 14:48:54
2016-04-12 14:48:57
2016-04-12 14:48:58
2016-04-12 14:48:59
2016-04-12 14:49:00
2016-04-12 14:49:02
2016-04-12 14:49:03
2016-04-12 14:49:04
2016-04-12 14:49:07
2016-04-12 14:49:08
2016-04-12 14:49:10
2016-04-12 14:49:11
2016-04-12 14:49:12
2016-04-12 14:49:22
2016-04-12 14:49:23
2016-04-12 14:49:24
2016-04-12 14:49:25
2016-04-12 14:49:26
key=2,val=tianxiang
key=1,val=zhang
2016-04-12 14:49:33
2016-04-12 14:49:34
2016-04-12 14:49:35


   


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章