分布式服务器布置须要使用到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值和服务器数量进行虚拟节点扩展。 算法