写点什么

一致性 hash 算法及实现

用户头像
关注
发布于: 2020 年 09 月 20 日

原理:

先构造一个长度为2的32次方的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 2的32次方-1])将服务器节点放置在这个Hash环上,然后根据数据的Key值计算得到其Hash值(其分布也为[0, 2的32次方-1]),接着在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点,完成Key到服务器的映射查找。



实现:

package leetcode;
import java.util.*;
/**
* 一致性Hash算法实现
*/
public class ConsistencyHash {
private static SortedMap<Integer, String> sortedMap = new TreeMap<>();
private List<String> nodeList;
public ConsistencyHash(List<String> nodeList) {
this.nodeList = nodeList;
nodeList.forEach(x -> {
addNode(x);
});
}
private void addNode(String node) {
if (node == null) {
return;
}
int hash = getHash(node);
sortedMap.put(hash, node);
System.out.println("hash = " + hash + " , node = " + node);
}
/**
* 使用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;
}
public static String getSever(String node){
// 得到带路由的结点的Hash值
int hash = getHash(node);
// 得到大于该Hash值的所有Map
SortedMap<Integer,String> sMap = sortedMap.tailMap(hash);
// 第一个Key就是顺时针过去离node最近的那个结点
Integer k = sMap.firstKey();
// 返回对应的服务器名称
return sMap.get(k);
}
}



package leetcode;
import java.util.Arrays;
import java.util.List;
/**
* 致性Hash算法调用
*/
public class Main {
public static void main(String[] args) {
String[] list = {"192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111",
"192.168.0.3:111", "192.168.0.4:111"};
List<String> nodeList = Arrays.asList(list);
//初始化
ConsistencyHash hash = new ConsistencyHash(nodeList);
nodeList.forEach(x->{
System.out.println(" server : " + ConsistencyHash.getSever(x));
});
}
}



用户头像

关注

everything will be alright 2020.04.06 加入

还未添加个人简介

评论

发布
暂无评论
一致性hash算法及实现