緣起
關於一致性hash算法的原理,本文不做概述。本文說的是如何在java中實現一致性Hash算法。
代碼
package com.bxoon.test;
import java.util.*;
/**
* 一致性Hash
* @author zhongguangxi
*/
public class ConsistenceHash {
// 物理節點集合
private List<String> realNodes = new ArrayList<>();
// 虛擬節點數,用戶指定
private int viretalNums = 100;
// 物理節點與虛擬節點的對應關係存儲
private Map<String,List<Integer>> real2VirtualMap = new HashMap<>();
// 排序存儲結構紅黑樹,key是虛擬節點的hash值,value是物理節點
private SortedMap<Long,String> sortedMap = new TreeMap<>();
public ConsistenceHash(int viretalNums) {
super();
this.viretalNums = viretalNums;
}
public ConsistenceHash() {
super();
}
/**
* 添加物理節點
* @param node
*/
public void addService(String node){
String vnode = null;
int i = 0;
for (int count=0;count<viretalNums;){
i++;
vnode = node+"-"+i;
long hashValue = FNV1_32_HASH.hash(vnode);
if (!this.sortedMap.containsKey(hashValue)){
count++;
this.sortedMap.put(hashValue,node);
}
}
this.realNodes.add(node);
}
/**
* 刪除物理節點
* @param node
*/
public void removeService(String node){
}
/**
* 獲取數據的存取節點
* @param key
* @return
*/
public String getService(String key){
long hash = FNV1_32_HASH.hash(key);
SortedMap<Long,String> map = this.sortedMap.tailMap(hash);
if (map.isEmpty()){
return this.sortedMap.get(sortedMap.firstKey());
}else{
return map.get(map.firstKey());
}
}
/**
* 測試
* @param args
*/
public static void main(String[] args) {
ConsistenceHash consistenceHash = new ConsistenceHash();
consistenceHash.addService("193.168.1.10");
consistenceHash.addService("193.168.1.11");
consistenceHash.addService("193.168.1.12");
for (int i =0;i<100;i++){
System.out.println("a"+i+" 對應的服務器:"+consistenceHash.getService("a"+i));
}
}
}
輸出結果
a0 對應的服務器:193.168.1.12
a1 對應的服務器:193.168.1.12
a2 對應的服務器:193.168.1.12
a3 對應的服務器:193.168.1.11
a4 對應的服務器:193.168.1.10
a5 對應的服務器:193.168.1.11
a6 對應的服務器:193.168.1.10
a7 對應的服務器:193.168.1.12
a8 對應的服務器:193.168.1.10
a9 對應的服務器:193.168.1.11
a10 對應的服務器:193.168.1.12
a11 對應的服務器:193.168.1.12
a12 對應的服務器:193.168.1.12
a13 對應的服務器:193.168.1.12
a14 對應的服務器:193.168.1.11
a15 對應的服務器:193.168.1.10
a16 對應的服務器:193.168.1.10
a17 對應的服務器:193.168.1.10
a18 對應的服務器:193.168.1.10
a19 對應的服務器:193.168.1.10
a20 對應的服務器:193.168.1.12
a21 對應的服務器:193.168.1.12
a22 對應的服務器:193.168.1.10
a23 對應的服務器:193.168.1.10
a24 對應的服務器:193.168.1.12
a25 對應的服務器:193.168.1.10
a26 對應的服務器:193.168.1.12
a27 對應的服務器:193.168.1.11
a28 對應的服務器:193.168.1.10
a29 對應的服務器:193.168.1.12
a30 對應的服務器:193.168.1.12
a31 對應的服務器:193.168.1.12
a32 對應的服務器:193.168.1.12
a33 對應的服務器:193.168.1.12
a34 對應的服務器:193.168.1.12
a35 對應的服務器:193.168.1.10
a36 對應的服務器:193.168.1.10
a37 對應的服務器:193.168.1.11
a38 對應的服務器:193.168.1.10
a39 對應的服務器:193.168.1.11
a40 對應的服務器:193.168.1.11
a41 對應的服務器:193.168.1.11
a42 對應的服務器:193.168.1.12
a43 對應的服務器:193.168.1.10
a44 對應的服務器:193.168.1.12
a45 對應的服務器:193.168.1.11
a46 對應的服務器:193.168.1.10
a47 對應的服務器:193.168.1.11
a48 對應的服務器:193.168.1.10
a49 對應的服務器:193.168.1.10
a50 對應的服務器:193.168.1.10
a51 對應的服務器:193.168.1.10
a52 對應的服務器:193.168.1.12
a53 對應的服務器:193.168.1.10
a54 對應的服務器:193.168.1.10
a55 對應的服務器:193.168.1.11
a56 對應的服務器:193.168.1.10
a57 對應的服務器:193.168.1.11
a58 對應的服務器:193.168.1.12
a59 對應的服務器:193.168.1.12
a60 對應的服務器:193.168.1.12
a61 對應的服務器:193.168.1.11
a62 對應的服務器:193.168.1.12
a63 對應的服務器:193.168.1.10
a64 對應的服務器:193.168.1.12
a65 對應的服務器:193.168.1.12
a66 對應的服務器:193.168.1.11
a67 對應的服務器:193.168.1.10
a68 對應的服務器:193.168.1.12
a69 對應的服務器:193.168.1.12
a70 對應的服務器:193.168.1.11
a71 對應的服務器:193.168.1.12
a72 對應的服務器:193.168.1.12
a73 對應的服務器:193.168.1.10
a74 對應的服務器:193.168.1.12
a75 對應的服務器:193.168.1.10
a76 對應的服務器:193.168.1.12
a77 對應的服務器:193.168.1.10
a78 對應的服務器:193.168.1.10
a79 對應的服務器:193.168.1.11
a80 對應的服務器:193.168.1.12
a81 對應的服務器:193.168.1.10
a82 對應的服務器:193.168.1.12
a83 對應的服務器:193.168.1.12
a84 對應的服務器:193.168.1.12
a85 對應的服務器:193.168.1.12
a86 對應的服務器:193.168.1.10
a87 對應的服務器:193.168.1.10
a88 對應的服務器:193.168.1.11
a89 對應的服務器:193.168.1.10
a90 對應的服務器:193.168.1.11
a91 對應的服務器:193.168.1.12
a92 對應的服務器:193.168.1.11
a93 對應的服務器:193.168.1.12
a94 對應的服務器:193.168.1.10
a95 對應的服務器:193.168.1.11
a96 對應的服務器:193.168.1.11
a97 對應的服務器:193.168.1.10
a98 對應的服務器:193.168.1.10
a99 對應的服務器:193.168.1.11
結論
可以看到測試結果,每一個key都落在了對應的節點上。
基本原理
1.添加物理節點的時候要添加對應的虛擬節點
2.在一個Map<String,Node>中保存虛擬節點和物理節點的對應關係,其中key爲虛擬節點的Hash,而value爲物理節點
3.在獲取節點的時候,根據某個key的hash值得到離他最近的一個節點,如果沒有的話則取集合中第一個節點,這樣就形成了一個環。