架构师训练营第五周作业
发布于: 2020 年 07 月 08 日
代码部分:
package Week5;import java.util.*;public class Hash { //待添加入Hash环的真实服务器节点列表 private static LinkedList<Node> realNodes = new LinkedList<>(); //虚拟节点列表 private static SortedMap<Integer, Node> sortedMap = new TreeMap<Integer, Node>(); static { //初始化服务器数量 for (int i = 0; i < 10; i++) { String nodeName = "server"+i; Node node = new Node(nodeName); realNodes.add(node); } //引入虚拟节点: 添加1000倍虚拟节点,将10台server对应的虚拟节点放入TreeMap中 for (Node node : realNodes) { for (int i = 1; i <=1000; i++) { String nodeName = node.getName() + "-VM" + String.valueOf(i); int hash = getHash(nodeName); sortedMap.put(hash, node); } } } //计算服务器的Hash值 private static int getHash(String str) { final int p = 16775519; 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; } //得到应当路由到的结点 private static Node getServer(String key) { //得到该key的hash值 int hash = getHash(key); //得到大于该Hash值的所有Map Node server; SortedMap<Integer, Node> subMap = sortedMap.tailMap(hash); if (subMap.isEmpty()) { //如果没有比该key的hash值大的,则从第一个node开始 Integer i = sortedMap.firstKey(); //返回对应的服务器 server = sortedMap.get(i); } else { //第一个Key就是顺时针过去离node最近的那个结点 Integer i = subMap.firstKey(); //返回对应的服务器 server= subMap.get(i); } if(server!=null) { server.put(key,hash+""); System.out.println(server.getName()); } return server; } //获取实际服务器上负载平均值 public static double getAverage(LinkedList<Node> arr) { double sum = 0; int number = arr.size(); for (int i = 0; i < number; i++) { Node node =arr.get(i); sum += node.getCount(); } return sum / number; } //获取实际服务器上负载的标准差 public static double getStandardDevition(LinkedList<Node> arr) { double sum = 0; int number = arr.size(); double avgValue = getAverage(arr);//获取平均值 for (int i = 0; i < number; i++) { Node node =arr.get(i); sum += Math.pow((node.getCount() - avgValue), 2); } return Math.sqrt((sum / (number - 1))); } public static void main(String[] args) { //模拟节点 for (int i = 0; i < 1000000; i++) { String key = "用户:"+i; System.out.println(key + "的hash值为" + getHash(key) + ", 对应结点:" + getServer(key).getName() + ""); } //打印 Node的实际负载 for (int i = 0; i < realNodes.size(); i++) { Node node = realNodes.get(i); System.out.println("服务器:" + node.getName()+",对应用户数量:"+node.getCount()); } System.out.println("标准差:"+getStandardDevition(realNodes)+""); } }
package Week5;import java.util.*;public class Node { private String domain; private int count = 0; private Map<String, Object> data = new HashMap(); public Node(String domain) { this.domain= domain; } public <T> void put(String key,String value) { data.put(key,value); count++; } public void remove(String key){ data.remove(key); count--; } public <T> T get(String key) { return (T) data.get(key); } public int getCount() { return count; } public String getName() { return domain; }}
输出结果:
服务器:server0,对应用户数量:98435
服务器:server1,对应用户数量:100688
服务器:server2,对应用户数量:100607
服务器:server3,对应用户数量:101330
服务器:server4,对应用户数量:98581
服务器:server5,对应用户数量:94960
服务器:server6,对应用户数量:105492
服务器:server7,对应用户数量:97796
服务器:server8,对应用户数量:99354
服务器:server9,对应用户数量:102757
标准差:2896.6095890042056
划线
评论
复制
发布于: 2020 年 07 月 08 日阅读数: 45
王铭铭
关注
还未添加个人签名 2020.01.14 加入
还未添加个人简介
评论