标签:
分布式服务器布置需要使用到hash算法,设节点有N个,普通的哈希算法:key%N,在遇到节点增加和减少的情况下,对于单纯的逻辑计算hash是没有问题的,但如果节点集群提供存储功能,那效果就不理想了。这时候我们的想法是在增加节点时以前的节点不受影响,在减少节点时只有与减少节点相关的受影响。那么我们不能单纯的使用%的方式,有个解决方案是将对象key和服务器节点key抽象出来,间隔排布在一个圆环上面,安装顺时针的方式对象key取的最近的服务器节点。这个方法就是ConsistentHash,下面贴出算法的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); } }
一种实现方案:
使用tree管理服务器节点,每个服务器节点保存一份能索引到它的hash key列表(实际应用以分布式IP哈希为居多),访问的时候计算key的hash值与tree管理的列表进行对比查找,找到对应的映射服务器。tree管理的服务器节点不太好决定的话只能是根据keyhash值和服务器数量进行虚拟节点扩展。
标签:
原文地址:http://my.oschina.net/u/659405/blog/387457