標籤:des style blog http color java 使用 os 檔案
一個簡單的consistent hashing的範例,非常easy理解。
首先有一個裝置類,定義了機器名和ip:
public class Cache{public String name;public String ipAddress;}
然後是基本的實現:
public class Shard<T> { //hash 演算法並非保證絕對的平衡,假設 cache 較少的話,對象並不能被均勻的映射到 cache 上,//所以添加虛擬節點private TreeMap<Long, T> nodes;private List<T> shards; //節點片段private final int NODE_NUM = 10; // 每一個機器節點關聯的虛擬節點個數public Shard(List<T> shards) {this.shards = shards;init();}private void init() { nodes = new TreeMap<Long, T>();for (int i = 0; i < shards.size(); i++) { // 遍曆真實節點final T shardInfo = shards.get(i);for (int n = 0; n < NODE_NUM; n++){// 真實節點關聯虛擬節點,真實節點是VALUE;nodes.put((long) Hash("SHARD-" + i + "-NODE-" + n), shardInfo);}System.out.println(shardInfo);}}public T getShardInfo(String key) {SortedMap<Long, T> tail = nodes.tailMap((long) Hash(key)); if (tail.size() == 0) {return nodes.get(nodes.firstKey());}//找到近期的虛擬節點return tail.get(tail.firstKey());}/** * 改進的32位FNV演算法,高離散 * * @param string * 字串 * @return int值 */ public static int Hash(String str) { final int p = 16777619; int hash = (int) 2166136261L; for (byte b : str.getBytes()) hash = (hash ^ b) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return hash; }}
到這裡就完了,是不是非常easy,以下來測試下:
public class Test{/** * @param args */public static void main(String[] args){List<Cache> myCaches=new ArrayList<Cache>();Cache cache1=new Cache();cache1.name="COMPUTER1";Cache cache2=new Cache();cache2.name="COMPUTER2";myCaches.add(cache1);myCaches.add(cache2);Shard<Cache> myShard=new Shard<Cache>(myCaches);Cache currentCache=myShard.getShardInfo("info1");System.out.println(currentCache.name);//for(int i=0;i<20;i++)//{//String object=getRandomString(20);//產生20位長度的隨機字串//Cache currentCache=myShard.getShardInfo(object);//System.out.println(currentCache.name);//}}public static String getRandomString(int length) { //length表示產生字串的長度 String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } }
我們有兩台裝置,computer1和computer2,第一次初始化要構建一個2的32次方的環,並往上面放裝置。這個環由改進的FNV演算法實現。位置也由hash演算法確定。
但我們僅僅有兩台裝置,非常明顯在環上會分布不均勻(這個就不解釋了,網上非常多資料)。於是我們每台裝置添加10個虛擬設備。
最後分布例如以下:
[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected]
-2147483648到2147483647之間是不是比較均勻,這是java的,假設是c#的就是0~2的32次方。我們hash計算出KEY值為2049553054,然後順時針找到近期的位置,即為
[email protected]
結果我們定位到了COMPUTER1
最好我們要看看平衡性怎樣:取消上面凝視的代碼,迴圈20次,得到結果例如以下:
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER1
COMPUTER1
COMPUTER2
COMPUTER2
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER1
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2
大家能夠自己取試試,
FNV雜湊演算法是一種高離散性的雜湊演算法,特別適用於雜湊很相似的字串,比如:URL,IP,主機名稱,檔案名稱等。
下面服務使用了FNV:
1、calc
2、DNS
3、mdbm key/value查詢函數
4、資料庫索引hash
5、主流web查詢/索引引擎
6、高效能email服務
7、基於訊息ID查詢函數
8、auti-spam反垃圾郵件過濾器
9、NFS實現(比方freebsd 4.3, linux NFS v4)
10、Cohesia MASS project
11、Ada 95的spellchecker
12、開源x86彙編器:flatassembler user-defined symbol hashtree
13、PowerBASIC
14、PS2、XBOX上的文本資源
15、非加密圖形檔案指紋
16、FRET
17、Symbian DASM
18、VC++ 2005的hash_map實現
19、memcache中的libketama
20、 PHP 5.x
21、twitter中用於改進cache片段
22、BSD IDE project
23、deliantra game server
24、 Leprechaun
25、IPv6流標籤
一致性雜湊演算法(consistent hashing)範例+測試。