package xyz.anduo.crawler.hash;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* 一致hash算法的实现
*
* @author anduo
*
* @param <T>
*/
public class ConsistentHash<T> {
private final HashFunction hashFunction; // hash 函数接口
private final int numberOfReplicas;// 每个机器节点关联的虚拟节点个数
private final SortedMap<Long, T> circle = new TreeMap<Long, T>();// 环形虚拟节点
/**
* @param hashFunction hash 函数接口
* @param numberOfReplicas 每个机器节点关联的虚拟节点个数
* @param nodes 真实机器节点
*/
public ConsistentHash(HashFunction hashFunction, int numberOfReplicas, Collection<T> nodes// 物理节点
) {
this.hashFunction = hashFunction;
this.numberOfReplicas = numberOfReplicas;
for (T node : nodes) {
add(node);
}
}
/**
* 增加真实机器节点
*
* @param node
*/
public void add(T node) {
for (int i = 0; i < numberOfReplicas; i++) {
circle.put(hashFunction.hash(node.toString() + i), node);
}
}
/**
* 删除真实机器节点
*
* @param node
*/
public void remove(T node) {
for (int i = 0; i < numberOfReplicas; i++) {
circle.remove(hashFunction.hash(node.toString() + i));
}
}
/**
* 取得真实机器节点
*
* @param key
* @return
*/
public T get(String key) {// 关键算法
if (circle.isEmpty()) {
return null;
}
// 计算hash值
Long hash = hashFunction.hash(key);
// 如果不包含这个hash值
if (!circle.containsKey(hash)) {
SortedMap<Long, T> tailMap = circle.tailMap(hash);// 沿环的顺时针找到一个虚拟节点
hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
}
return circle.get(hash);// 返回该虚拟节点对应的真实机器节点的信息
}
}