架构师训练营第 5 周命题作业
发布于: 2020 年 07 月 08 日
用你熟悉的编程语言实现一致性 hash 算法
package algorithm.hash;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;
public class ConsistentHash<T> {
// 虚拟节点的数量
private final int virtualNodeNum;
private final SortedMap<Integer, T> consistenHashCircle = new TreeMap<Integer, T>();
public ConsistentHash(int virtualNodeNum, Collection<T> nodes) {
this.virtualNodeNum = virtualNodeNum;
for (T node : nodes) {
add(node);
}
}
// 新增一个实际节点
public void add(T node) {
for (int i = 0; i < virtualNodeNum; i++) {
String nodestr = node.toString() + Math.pow((double) i, (double) 6);
int hashcode = nodestr.hashCode();
consistenHashCircle.put(hashcode, node);
}
}
// 删除一个实际节点
public void remove(T node) {
for (int i = 0; i < virtualNodeNum; i++) {
String nodestr = node.toString() + Math.pow((double) i, (double) 6);
consistenHashCircle.remove(nodestr.hashCode());
}
}
// 获取数据要存放的实际节点
public T get(Object key) {
if (consistenHashCircle.isEmpty()) {
return null;
}
int hash = key.hashCode();
if (!consistenHashCircle.containsKey(hash)) {
SortedMap<Integer, T> tailMap = consistenHashCircle.tailMap(hash);
hash = tailMap.isEmpty() ? consistenHashCircle.firstKey() : tailMap.firstKey();
}
return consistenHashCircle.get(hash);
}
}
复制代码
编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性
package algorithm.hash;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class ConsistentHashTest<T> {
// 求和
static int Sum(int[] data) {
int sum = 0;
for (int i = 0; i < data.length; i++)
sum = sum + data[i];
return sum;
}
// 求平均值
static double Mean(int[] data) {
int mean = 0;
mean = Sum(data) / data.length;
return mean;
}
// 求总体方差
static double POP_Variance(int[] data) {
double variance = 0;
for (int i = 0; i < data.length; i++) {
variance = variance + (Math.pow((data[i] - Mean(data)), 2));
}
variance = variance / data.length;
return variance;
}
// 求总体标准差
static double POP_STD_dev(int[] data) {
double std_dev;
std_dev = Math.sqrt(POP_Variance(data));
return std_dev;
}
// 求样本方差
static double Sample_Variance(int[] data) {
double variance = 0;
for (int i = 0; i < data.length; i++) {
variance = variance + (Math.pow((data[i] - Mean(data)), 2));
}
variance = variance / (data.length - 1);
return variance;
}
// 求样本标准差
static double Sample_STD_dev(int[] data) {
double std_dev;
std_dev = Math.sqrt(Sample_Variance(data));
return std_dev;
}
public static void main(String[] args) {
Set<String> nodes = new HashSet<String>();
int[] countArrays = new int[10];
for (int i = 1; i < 11; i++) {
nodes.add("192.168.0." + i);
countArrays[i - 1] = 0;
}
ConsistentHash<String> consistentHash = new ConsistentHash<String>(200, nodes);
Random random = new Random();
for (int i = 0; i < 1000000; i++) {
String node = consistentHash.get("" + random.nextInt(1000000) + System.currentTimeMillis() % 100);
switch (node) {
case "192.168.0.1":
countArrays[0]++;
break;
case "192.168.0.2":
countArrays[1]++;
break;
case "192.168.0.3":
countArrays[2]++;
break;
case "192.168.0.4":
countArrays[3]++;
break;
case "192.168.0.5":
countArrays[4]++;
break;
case "192.168.0.6":
countArrays[5]++;
break;
case "192.168.0.7":
countArrays[6]++;
break;
case "192.168.0.8":
countArrays[7]++;
break;
case "192.168.0.9":
countArrays[8]++;
break;
case "192.168.0.10":
countArrays[9]++;
break;
}
}
System.out.println("总体标准差为:" + POP_STD_dev(countArrays));
System.out.println("样本标准差为:" + Sample_STD_dev(countArrays));
}
}
复制代码
运行测试程序,5 次测试汇总结果如下
总体标准差为:5798.654309406623
样本标准差为:6112.318327225222
总体标准差为:5972.901120895942
样本标准差为:6295.99059366797
总体标准差为:5788.0663956108865
样本标准差为:6101.157686137207
总体标准差为:5662.06605401244
样本标准差为:5968.341664333756
体标准差为:5969.317867227377
样本标准差为:6292.21351265903
复制代码
划线
评论
复制
发布于: 2020 年 07 月 08 日阅读数: 62
hifly
关注
还未添加个人签名 2018.03.08 加入
还未添加个人简介
评论