架构师训练营第 2 期 第五周作业
发布于: 2020 年 11 月 23 日
题目:测试 100 万 KV 数据,10 个服务器节点的情况下,计算了这些 KV 数据在服务器上分布数量的标准差。(代码中计算了方差)
//存放缓存服务器节点 key:hashcode value: serviceName private static TreeMap<Integer, String> memServiceMap = new TreeMap<>(); //每台机器的虚拟节点数 private static int vmNoteNum = 100; //真实缓存服务器数量 private static int serverSum = 10; //请求数量 private static int clientSum = 1000000; public static void main(String[] args) { //虚拟节点数取值 int[] testNum = new int[]{50, 100, 150, 200, 250}; for (int i = 0; i < testNum.length; i++) { //清除数据 memServiceMap.clear(); vmNoteNum = testNum[i]; cal(); } } //KV 数据在服务器上分布数量的方差 private static void cal() { //10台机器 初始化 for (int i = 0; i < serverSum; i++) { addMemServiceMap("service" + i); } String[] clients = new String[clientSum]; //准备100 万 KV 数据 Random random = new Random(); for (int i = 0; i < clientSum; i++) { clients[i] = random.nextInt(256) + "." + random.nextInt(256) + "." + random.nextInt(256) + "." + random.nextInt(256) + ":" + random.nextInt(9999); } Map<String, Integer> countMap = new HashMap<>(); String serverName; for (int i = 0; i < clientSum; i++) { //模拟一次映射 serverName = getService(clients[i]); //计数 if (countMap.containsKey(serverName)) { countMap.put(serverName, countMap.get(serverName) + 1); } else { countMap.put(serverName, 1); } } //统计服务器访问次数 保存至 arr Set<String> countKey = countMap.keySet(); int[] arr = new int[countKey.size()]; Iterator<String> it = countKey.iterator(); int flag = 0; while (it.hasNext()) { arr[flag++] = countMap.get(it.next()); } //打印 方差 System.out.println("每台服务器虚拟节点数:" + vmNoteNum + " 当前方差: " + Double.toString(variance(arr))); } /** * 根据请求返回要访问的服务器IP * * @param key 一次请求相关的信息(如请求方的IP) * @return 请求访问的服务器IP */ public static String getService(String key) { int hashcode = getHash(key); SortedMap<Integer, String> sortedMap = memServiceMap.tailMap(hashcode); //查找第一个比当前HASH值大的节点,若未找到,则取第一个节点 return sortedMap.size() > 0 ? memServiceMap.get(sortedMap.firstKey()) : memServiceMap.firstEntry().getValue(); } /** * 增加节点 * * @param serviceName 提供访问的服务器 */ private static void addMemServiceMap(String serviceName) { for (int j = 0; j < vmNoteNum; j++) { memServiceMap.put(getHash(serviceName + "_visual" + j), serviceName); } } /** * 删除服务器节点 * * @param serviceName 需要删除的服务器 */ private static void removeMemServiceMap(String serviceName) { for (int i = 0; i < vmNoteNum; i++) { memServiceMap.remove(getHash(serviceName + "_visual" + i)); } } //抄来的获取hash方法 private static int getHash(String key) { final int FNV_32_PRIME = 16777619; int hash = (int) 2166136261L; for (int i = 0; i < key.length(); i++) { hash = (hash ^ key.charAt(i)) * FNV_32_PRIME; } hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return hash < 0 ? Math.abs(hash) : hash; } // 抄来的方差的计算公式 private static double variance(int[] arr) { int m = arr.length; double sum = 0; for (int value : arr) { sum += value; } double dAve = sum / m; double dVar = 0; for (int value : arr) { dVar += (value - dAve) * (value - dAve); } return dVar / m; }
输出结果:
划线
评论
复制
发布于: 2020 年 11 月 23 日阅读数: 21
月下独酌
关注
还未添加个人签名 2019.07.22 加入
还未添加个人简介
评论