一致性hash算法Java demo
package com.wang.hash;
import java.util.LinkedList;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* 一致性hash算法
*/
public class ConsistentHashingWithVirtualNode {
// 服务器地址
private static String[] serverNode = {"192.168.0.0:111", "192.167.0.0:111", "192.166.0.0:111", "192.165.0.0:111", "192.158.0.0:111", "192.148.0.0:111"};
// 虚拟节点数
private static final int VIRTUAL_NODE = 100;
// 虚拟节点map
private static SortedMap<Integer, String> virtualNodeMap = new TreeMap<>();
// 真实节点链表
private static LinkedList<String> realServerNodeList = new LinkedList<>();
/**
* 创建虚拟节点
*/
static {
for (int i = 0; i < serverNode.length; i++) {
realServerNodeList.add(serverNode[i]);
}
for (String realNode : realServerNodeList) {
for (int j = 0; j < VIRTUAL_NODE; j++) {
String nodeName = realNode + "&&" + String.valueOf(j);
Integer hash = getHash(nodeName);
virtualNodeMap.put(hash, realNode + "&&VN" + j);
System.out.println("节点是:【" + nodeName + "】加入到虚拟节点节点集合中" + "hash值是:" + hash);
}
System.out.println();
}
}
/**
* 使用FNV1_32_HASH算法计算服务器的Hash值,这里不使用重写hashCode的方法,最终效果没区别
*/
private static int getHash(String str) {
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < str.length(); i++) {
hash = (hash ^ str.charAt(i)) * p;
}
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
// 如果算出来的值为负数则取其绝对值
if (hash < 0) {
hash = Math.abs(hash);
}
return hash;
}
/**
* @param node
* @return
*/
public static String getServer(String node) {
// 计算node 的hash值
Integer hash = getHash(node);
// 获取比它hash值大的node集合
SortedMap<Integer, String> minVirtualNodeMap = virtualNodeMap.tailMap(hash);
// 获取最小的node
Integer nodeKey = minVirtualNodeMap.firstKey();
// 获取虚拟的node节点
String virtualNode = virtualNodeMap.get(nodeKey);
return virtualNode.substring(0, virtualNode.lastIndexOf("&&"));
}
public static void main(String[] args) {
for (int i = 0; i < serverNode.length; i++) {
System.out.println("节点是【" + serverNode[i] + "】存储在【" + getServer(serverNode[i]) + "】节点上");
}
}
}
输出:
节点是:【192.168.0.0:111&&0】加入到虚拟节点节点集合中hash值是:1675293881
节点是:【192.168.0.0:111&&1】加入到虚拟节点节点集合中hash值是:589251333
节点是:【192.168.0.0:111&&2】加入到虚拟节点节点集合中hash值是:1714252943
节点是:【192.168.0.0:111&&3】加入到虚拟节点节点集合中hash值是:506543973
节点是:【192.168.0.0:111&&4】加入到虚拟节点节点集合中hash值是:1830535493
节点是:【192.168.0.0:111&&5】加入到虚拟节点节点集合中hash值是:759932604
节点是:【192.168.0.0:111&&6】加入到虚拟节点节点集合中hash值是:1682530966
节点是:【192.168.0.0:111&&7】加入到虚拟节点节点集合中hash值是:1657566804
节点是:【192.168.0.0:111&&8】加入到虚拟节点节点集合中hash值是:1428964732
节点是:【192.168.0.0:111&&9】加入到虚拟节点节点集合中hash值是:145596275
节点是:【192.167.0.0:111&&0】加入到虚拟节点节点集合中hash值是:139440351
节点是:【192.167.0.0:111&&1】加入到虚拟节点节点集合中hash值是:544440280
节点是:【192.167.0.0:111&&2】加入到虚拟节点节点集合中hash值是:361440290
节点是:【192.167.0.0:111&&3】加入到虚拟节点节点集合中hash值是:73550959
节点是:【192.167.0.0:111&&4】加入到虚拟节点节点集合中hash值是:368195106
节点是:【192.167.0.0:111&&5】加入到虚拟节点节点集合中hash值是:612630783
节点是:【192.167.0.0:111&&6】加入到虚拟节点节点集合中hash值是:30366838
节点是:【192.167.0.0:111&&7】加入到虚拟节点节点集合中hash值是:261843626
节点是:【192.167.0.0:111&&8】加入到虚拟节点节点集合中hash值是:929016166
节点是:【192.167.0.0:111&&9】加入到虚拟节点节点集合中hash值是:682057230
节点是:【192.166.0.0:111&&0】加入到虚拟节点节点集合中hash值是:755314198
节点是:【192.166.0.0:111&&1】加入到虚拟节点节点集合中hash值是:494606552
节点是:【192.166.0.0:111&&2】加入到虚拟节点节点集合中hash值是:1238666724
节点是:【192.166.0.0:111&&3】加入到虚拟节点节点集合中hash值是:1493512675
节点是:【192.166.0.0:111&&4】加入到虚拟节点节点集合中hash值是:105358628
节点是:【192.166.0.0:111&&5】加入到虚拟节点节点集合中hash值是:969326055
节点是:【192.166.0.0:111&&6】加入到虚拟节点节点集合中hash值是:804741711
节点是:【192.166.0.0:111&&7】加入到虚拟节点节点集合中hash值是:758329520
节点是:【192.166.0.0:111&&8】加入到虚拟节点节点集合中hash值是:402804487
节点是:【192.166.0.0:111&&9】加入到虚拟节点节点集合中hash值是:578927400
节点是:【192.165.0.0:111&&0】加入到虚拟节点节点集合中hash值是:1673788001
节点是:【192.165.0.0:111&&1】加入到虚拟节点节点集合中hash值是:1835552614
节点是:【192.165.0.0:111&&2】加入到虚拟节点节点集合中hash值是:1990694038
节点是:【192.165.0.0:111&&3】加入到虚拟节点节点集合中hash值是:1310987770
节点是:【192.165.0.0:111&&4】加入到虚拟节点节点集合中hash值是:2019534440
节点是:【192.165.0.0:111&&5】加入到虚拟节点节点集合中hash值是:1200390317
节点是:【192.165.0.0:111&&6】加入到虚拟节点节点集合中hash值是:984938106
节点是:【192.165.0.0:111&&7】加入到虚拟节点节点集合中hash值是:1957193416
节点是:【192.165.0.0:111&&8】加入到虚拟节点节点集合中hash值是:699987518
节点是:【192.165.0.0:111&&9】加入到虚拟节点节点集合中hash值是:2112580768
节点是:【192.158.0.0:111&&0】加入到虚拟节点节点集合中hash值是:821236798
节点是:【192.158.0.0:111&&1】加入到虚拟节点节点集合中hash值是:1827208141
节点是:【192.158.0.0:111&&2】加入到虚拟节点节点集合中hash值是:44693840
节点是:【192.158.0.0:111&&3】加入到虚拟节点节点集合中hash值是:567385565
节点是:【192.158.0.0:111&&4】加入到虚拟节点节点集合中hash值是:296326993
节点是:【192.158.0.0:111&&5】加入到虚拟节点节点集合中hash值是:570379445
节点是:【192.158.0.0:111&&6】加入到虚拟节点节点集合中hash值是:343443391
节点是:【192.158.0.0:111&&7】加入到虚拟节点节点集合中hash值是:58380255
节点是:【192.158.0.0:111&&8】加入到虚拟节点节点集合中hash值是:1538393729
节点是:【192.158.0.0:111&&9】加入到虚拟节点节点集合中hash值是:1850414955
节点是:【192.148.0.0:111&&0】加入到虚拟节点节点集合中hash值是:222531453
节点是:【192.148.0.0:111&&1】加入到虚拟节点节点集合中hash值是:1398803220
节点是:【192.148.0.0:111&&2】加入到虚拟节点节点集合中hash值是:1805765854
节点是:【192.148.0.0:111&&3】加入到虚拟节点节点集合中hash值是:1419686318
节点是:【192.148.0.0:111&&4】加入到虚拟节点节点集合中hash值是:1583766768
节点是:【192.148.0.0:111&&5】加入到虚拟节点节点集合中hash值是:334794917
节点是:【192.148.0.0:111&&6】加入到虚拟节点节点集合中hash值是:54764593
节点是:【192.148.0.0:111&&7】加入到虚拟节点节点集合中hash值是:1974928667
节点是:【192.148.0.0:111&&8】加入到虚拟节点节点集合中hash值是:558831114
节点是:【192.148.0.0:111&&9】加入到虚拟节点节点集合中hash值是:1946349852
节点是【192.168.0.0:111】存储在【192.166.0.0:111】节点上
节点是【192.167.0.0:111】存储在【192.148.0.0:111】节点上
节点是【192.166.0.0:111】存储在【192.165.0.0:111】节点上
节点是【192.165.0.0:111】存储在【192.158.0.0:111】节点上
节点是【192.158.0.0:111】存储在【192.148.0.0:111】节点上
节点是【192.148.0.0:111】存储在【192.167.0.0:111】节点上