ConsistentHash 一致性哈希

分佈式服務器佈置須要使用到hash算法,設節點有N個,普通的哈希算法:key%N,在遇到節點增長和減小的狀況下,對於單純的邏輯計算hash是沒有問題的,但若是節點集羣提供存儲功能,那效果就不理想了。這時候咱們的想法是在增長節點時之前的節點不受影響,在減小節點時只有與減小節點相關的受影響。那麼咱們不能單純的使用%的方式,有個解決方案是將對象key和服務器節點key抽象出來,間隔排布在一個圓環上面,安裝順時針的方式對象key取的最近的服務器節點。這個方法就是ConsistentHash,下面貼出算法的Java版本: java

import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

public class ConsistentHash<T> {
	 private final HashFunction hashFunction;// hash算法
	 private final int numberOfReplicas;// 虛擬節點數目
	 private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();
	 public ConsistentHash(HashFunction hashFunction, int numberOfReplicas,
	     Collection<T> nodes){ // 物理節點
	   this.hashFunction = hashFunction;
	   this.numberOfReplicas = numberOfReplicas;
	   for (T node : nodes) {
	     add(node);
	   }
	 }

	 public void add(T node) {
	   for (int i = 0; i < numberOfReplicas; i++) {
	     circle.put(hashFunction.hash(node.toString() + i), node);
	   }
	 }

	 public void remove(T node) {
	   for (int i = 0; i < numberOfReplicas; i++) {
	     circle.remove(hashFunction.hash(node.toString() + i));
	   }
	 }

	 public T get(Object key) {// 關鍵算法
	   if (circle.isEmpty()) {
	     return null;
	   }
	   // 計算hash值
	   int hash = hashFunction.hash(key);
	   // 若是不包括這個hash值
	   if (!circle.containsKey(hash)) {
	     SortedMap<Integer, T> tailMap = circle.tailMap(hash);
	     hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
	   }
	   return circle.get(hash);
	 }
}

一種實現方案: node

使用tree管理服務器節點,每一個服務器節點保存一份能索引到它的hash key列表(實際應用以分佈式IP哈希爲居多),訪問的時候計算key的hash值與tree管理的列表進行對比查找,找到對應的映射服務器。tree管理的服務器節點不太好決定的話只能是根據keyhash值和服務器數量進行虛擬節點擴展。 算法

相關文章
相關標籤/搜索