架构师第 5 周 - 作业
发布于: 2020 年 07 月 05 日
用你熟悉的编程语言实现一致性 hash 算法。
public class HashVirtualNode { // 服务器列表10台服务器 private static String[] servers = {"server0", "server1", "server2", "server3", "server4", "server5", "server6", "server7", "server8","server9"}; // 每个服务器节点对应的虚拟节点个数 private static final int VIRTUAL_NODES = 1; private static List<String> realNodes = new LinkedList<String>(); private static SortedMap<Integer, String> virtualNodes = new TreeMap<Integer, String>(); static{ for(int i=0; i<servers.length; i++) realNodes.add(servers[i]); for(String str : realNodes) { for(int i=0; i<VIRTUAL_NODES; i++){ String virtualNodeName = str + "_VN" + String.valueOf(i); int hash = getHash(virtualNodeName); virtualNodes.put(hash, virtualNodeName); } } } /** * 计算Hash值 * @param str * @return */ 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; } /** * 根据key得到应当路由到的结点 * @param key * @return */ private static String getServer(String key) { int hash = getHash(key); SortedMap<Integer, String> subMap = virtualNodes.tailMap(hash); String virtualNode; if (subMap.isEmpty()) { Integer i = virtualNodes.firstKey(); virtualNode = virtualNodes.get(i); } else { Integer i = subMap.firstKey(); virtualNode = subMap.get(i); } if(StringUtils.isNotBlank(virtualNode)) { return virtualNode.substring(0, virtualNode.indexOf("_")); } return null; }}
编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
public static void main(String[] args) { int[] serverNum = new int[10]; for(int i=1; i<=1000000; i++) { switch (getServer(String.valueOf(i))) { case "server0" : serverNum[0]++; break; case "server1" : serverNum[1]++; break; case "server2" : serverNum[2]++; break; case "server3" : serverNum[0]++; break; case "server4" : serverNum[0]++; break; case "server5" : serverNum[0]++; break; case "server6" : serverNum[0]++; break; case "server7" : serverNum[0]++; break; case "server8" : serverNum[0]++; break; case "server9" : serverNum[0]++; break; default: return; } } double result = getStandardDevition(serverNum); System.out.println("标准方差结果为:" + result); } /** * 根据标准方差计算方式计算 * @param arr * @return */ public static double getStandardDevition(int[] arr) { double sum = 0; // 平均应是每个服务器存放10万个KV值 double avgValue = 100000; int number = arr.length; for (int i = 0; i < number; i++) { System.out.println("server" + i + "存放KV 数据个数: " + arr[i]); sum += Math.pow((arr[i] - avgValue), 2); } return Math.sqrt((sum / (number - 1))); }
输出结果为:
划线
评论
复制
发布于: 2020 年 07 月 05 日 阅读数: 39
上山砍柴
关注
还未添加个人签名 2018.02.28 加入
还未添加个人简介
评论