io.github.linmoure.utils.hash.ConsistentHash Maven / Gradle / Ivy
package io.github.linmoure.utils.hash;
import java.util.Set;
import java.util.TreeMap;
/**
* @author lihenglin
* 一致性hash的实现
* Java implementation of consistent-hashing
*/
public class ConsistentHash {
private static final int DEFAULT_VIRTUAL_COUNT = 5;
/**
* 设置每个节点的虚拟节点个数,该参数默认是100
*/
private int virtualCount = DEFAULT_VIRTUAL_COUNT;
/**
* 设置一致性HASH的算法,默认采用 KETAMA_HASH
* 对于一致性HASH而言选择的HASH算法首先要考虑发散度其次再考虑性能
*/
private final HashAlgorithm alg;
private final Set nodeSet; //节点列表
private final TreeMap nodeMap;
private ConsistentHash(int virtualCount, Set nodeSet) {
this.virtualCount = virtualCount;
this.nodeSet = nodeSet;
this.alg = HashAlgorithm.KETAMA_HASH;
nodeMap = new TreeMap();
buildHashCircle();
}
private ConsistentHash(int virtualCount, Set nodeSet, HashAlgorithm alg) {
this.virtualCount = virtualCount;
this.nodeSet = nodeSet;
this.alg = alg;
nodeMap = new TreeMap();
buildHashCircle();
}
/**
* Get singleton of ConsistentHash
* 获取ConsistentHash的单例对象
*
* @param virtualCount 虚拟节点个数
* @param nodeSet 虚拟节点列表
* @return ConsistentHash
*/
public static ConsistentHash getInstance(int virtualCount, Set nodeSet) {
return new ConsistentHash(virtualCount, nodeSet);
}
public static ConsistentHash getInstance(int virtualCount, Set nodeSet, HashAlgorithm alg) {
return new ConsistentHash(virtualCount, nodeSet, alg);
}
/**
* 构建一致性HASH环
*/
private void buildHashCircle() {
if (nodeSet == null) return;
for (Node node : nodeSet) {
for (int i = 0; i < virtualCount; i++) {
long nodeKey = this.alg.hash(node.toString() + "-" + i);
nodeMap.put(nodeKey, node);
}
}
}
/**
* 沿环的顺时针找到虚拟节点
*
* @param key key
* @return io.github.linmoure.utils.hash.Node
*/
public Node findNodeByKey(String key) {
final Long hash = this.alg.hash(key);
Long target = hash;
if (!nodeMap.containsKey(hash)) {
target = nodeMap.ceilingKey(hash);
if (target == null && !nodeMap.isEmpty()) {
target = nodeMap.firstKey();
}
}
return nodeMap.get(target);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy