架构师训练营 -- 第五周作业

用户头像
花花大脸猫
关注
发布于: 2020 年 07 月 05 日
架构师训练营--第五周作业

用你熟悉的编程语言实现一致性hash算法

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public class HashConsistent {
/** 服务器列表,也可以从配置中读取相关配置 */
private static String[] servers = {"192.168.1.1:12", "192.168.1.2:12", "192.168.1.3:12",
"192.168.1.4:12", "192.168.1.5:12", "192.168.1.6:12", "192.168.1.7:12", "192.168.1.8:12",
"192.168.1.9:12", "192.168.1.10:12"};

/** 真实的server节点信息 */
private static List<String> realNodes = new LinkedList<String>();

private static SortedMap<Integer, String> map = new TreeMap<>();

/** 虚拟节点数量 也可以从配置中读取相关配置 */
private static final int VIRTUAL_NODE_SIZE = 50;

static {
for (String server : servers) {
realNodes.add(server);
}
for (String realNode : realNodes) {
for (int i = 0; i < VIRTUAL_NODE_SIZE; i++) {
String virtualNodeName = realNode + "&&VN" + i;
int hash = calculateHash(virtualNodeName);
map.put(hash, virtualNodeName);
}
}
}

public HashConsistent() {}

private static int calculateHash(String calStr) {
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < calStr.length(); i++) {
hash = (hash ^ calStr.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;
}

private static String getServer(String node) {
/** 得到带路由的结点的Hash值 */
int hash = calculateHash(node);
/** 得到大于该Hash值的所有Map */
SortedMap<Integer, String> subMap = map.tailMap(hash);
/** 第一个Key就是顺时针过去离node最近的那个结点 */
String virtualNode = subMap.get(subMap.firstKey());
return virtualNode.substring(0, virtualNode.indexOf("&&"));
}

public static void main(String[] args) {
Map<String, Integer> summary = new HashMap<>();
int keySize = 1000000;
ThreadLocalRandom random = ThreadLocalRandom.current();
for (int i = 0; i < keySize; i++) {
try {
int value = random.nextInt(keySize);
String server = getServer(String.valueOf(value));
if(summary.containsKey(server)){
summary.put(server, summary.get(server) + 1);
}else{
summary.put(server, 0);
}
}catch (Exception e){

}
}

Iterator<Map.Entry<String, Integer>> iterator = summary.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next();
System.out.println("server为"+ entry.getKey() + "分布了" + entry.getValue() +"个数据");
}
}

}

测试100万的数据,计算分布标准差,评估算法的负载均衡

执行结果如下所示:

server为192.168.1.10:12分布了72082个数据

server为192.168.1.3:12分布了97910个数据

server为192.168.1.2:12分布了80322个数据

server为192.168.1.1:12分布了109742个数据

server为192.168.1.4:12分布了124837个数据

server为192.168.1.5:12分布了92508个数据

server为192.168.1.8:12分布了92479个数据

server为192.168.1.9:12分布了89076个数据

server为192.168.1.7:12分布了124028个数据

server为192.168.1.6:12分布了116636个数据



目前来看负载均衡算法设置的数据分布还算均匀

用户头像

花花大脸猫

关注

小小老鼠小小老鼠不偷米大脸猫大脸猫爱吃鱼 2018.05.03 加入

一个默默无闻的码农大叔。。。。

评论

发布
暂无评论
架构师训练营--第五周作业