架构师训练营第五周作业
发布于: 2020 年 07 月 08 日
import java.util.Arrays;import java.util.Random;/** * @author ray.zhangr * @date 2020/7/8 9:57 下午 */public class ConsistentHash { private int serverNum; private int[] svrLocation; public ConsistentHash(int serverNum) { this.serverNum = serverNum; this.svrLocation = serverLocate(serverNum); } private int[] serverLocate(int serverNum) { int[] svrLocation = new int[serverNum]; for (int i = 0; i < serverNum; i++) { svrLocation[i] = new Random().nextInt(); // 用当前日期的哈希值模拟服务器的哈希值 } Arrays.sort(svrLocation); return svrLocation; } public int[] dataBelong(int[] keysHash) { int[] belongs = new int[serverNum]; for (int keyHash : keysHash) { for (int i = 0; i < serverNum; i++) { if (keyHash <= svrLocation[i]) { belongs[i]++; break; } } if (keyHash > svrLocation[serverNum - 1]) belongs[0]++; } return belongs; } public static void main(String args[]) { ConsistentHash ch = new ConsistentHash(10); int[] dataset = new int[1000000]; for (int i = 0; i < 1000000; i++) { dataset[i] = new Random().nextInt(); } int[] belongs = ch.dataBelong(dataset); for (int i = 0; i < belongs.length; i++) { System.out.println(String.format("Server %s: %s", i, belongs[i])); } // 评估标准差 System.out.println("标准差" + StandardDiviation(belongs)); } public static double StandardDiviation(int[] x) { int m=x.length; double sum=0; for(int i=0;i<m;i++){//求和 sum+=x[i]; } double dAve=sum/m;//求平均值 double dVar=0; for(int i=0;i<m;i++){//求方差 dVar+=(x[i]-dAve)*(x[i]-dAve); } //reture Math.sqrt(dVar/(m-1)); return Math.sqrt(dVar/m); }}
运行结果1:
运行结果2:
由于server的hash值分布不均匀,可以看出有的段内只落了几千个key,有的多的落了20w的key,分布在机器数量很少的情况下是不均匀的。所以用虚拟节点来看,就是为了最大化平均哈希环上机器的分布。
在群里看到不少同学已经实现了虚拟节点下的一致性hash算法,并用图表模拟了下虚拟节点数量和标准差的关系。贴出自己实现的虚拟节点的一致性哈希实现:
import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Random;/** * @author ray.zhangr * @date 2020/7/9 10:07 上午 */public class ConsistentHashWithVirtualNode { private int serverNum; private int multiple; private List<VirtualNode> nodes = new ArrayList<>(); public ConsistentHashWithVirtualNode(int serverNum, int multiple) { this.serverNum = serverNum; this.multiple = multiple; for (int i = 0; i < serverNum; i++) { for (int j = 0; j < multiple; j++) { VirtualNode node = new VirtualNode(new Random().nextInt(), i); nodes.add(node); } } Collections.sort(nodes); } public int[] dataBelong(int[] keysHash) { int[] belongs = new int[serverNum]; int virtualNodeNum = nodes.size(); for (int keyHash : keysHash) { for (int i = 0; i < virtualNodeNum; i++) { if (keyHash <= nodes.get(i).hashCode) { belongs[nodes.get(i).belongServer]++; break; } } if (keyHash > nodes.get(virtualNodeNum - 1).hashCode) belongs[nodes.get(virtualNodeNum - 1).belongServer]++; } return belongs; } class VirtualNode implements Comparable<VirtualNode> { private int hashCode; private int belongServer; VirtualNode(int hashCode, int belongServer) { this.hashCode = hashCode; this.belongServer = belongServer; } @Override public int compareTo(VirtualNode o) { return this.hashCode > o.hashCode ? 1 : -1; } } public static void main(String args[]) { ConsistentHashWithVirtualNode ch = new ConsistentHashWithVirtualNode(10, 20); int[] dataset = new int[1000000]; for (int i = 0; i < 1000000; i++) { dataset[i] = new Random().nextInt(); } int[] belongs = ch.dataBelong(dataset); for (int i = 0; i < belongs.length; i++) { System.out.println(String.format("Server %s: %s", i, belongs[i])); } // 评估标准差 System.out.println("标准差" + StandardDiviation(belongs)); } public static double StandardDiviation(int[] x) { int m=x.length; double sum=0; for(int i=0;i<m;i++){//求和 sum+=x[i]; } double dAve=sum/m;//求平均值 double dVar=0; for(int i=0;i<m;i++){//求方差 dVar+=(x[i]-dAve)*(x[i]-dAve); } //reture Math.sqrt(dVar/(m-1)); return Math.sqrt(dVar/m); }}
运行两次的实验结果如下:
可以看到标准差有明显的降低。虽然还是10个节点,但是每个节点分配的key数量比较均等,没再出现只有几千的key分配的情况。
划线
评论
复制
发布于: 2020 年 07 月 08 日阅读数: 50
张锐
关注
还未添加个人签名 2018.08.07 加入
还未添加个人简介
评论