一致性哈希算法 JAVA 版简单验证
发布于: 2020 年 07 月 08 日
用熟悉的编程语言实现一致性 hash 算法。
编写测试用例测试这个算法,测试 100 万 KV 数据,10 个服务器节点的情况下,计算这些 KV 数据在服务器上分布数量的标准差,以评估算法的存储负载不均衡性。
public class ConsistentHash { //模拟 10个物理物理节点 ip private Set<String> realIPNodes = new TreeSet<String>() {{ add("192.168.1.1"); add("192.168.1.2"); add("192.168.1.3"); add("192.168.1.4"); add("192.168.1.5"); add("192.168.1.6"); add("192.168.1.7"); add("192.168.1.8"); add("192.168.1.9"); add("192.168.1.10"); } }; private final int copies = 100000; // 复制倍数 private TreeMap<Long, String> virtualNodes = new TreeMap<>(); // 哈希值 -> 物理节点 private static Long FNVHash(String key) { final int p = 16777619; Long hash = 2166136261L; for (int idx = 0, num = key.length(); idx < num; ++idx) { hash = (hash ^ key.charAt(idx)) * 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; } // 根据物理节点,构建虚拟节点映射关系 public ConsistentHash() { for (String nodeIp : realIPNodes) { addPhysicalNode(nodeIp); } } // 添加物理节点 public void addPhysicalNode(String nodeIp) { for (int idx = 0; idx < copies; ++idx) { long hash = FNVHash(nodeIp + "#" + idx); virtualNodes.put(hash, nodeIp); } } // 查找对象映射的节点 public String getObjectNode(String object) { long hash = FNVHash(object); SortedMap<Long, String> tailMap = virtualNodes.tailMap(hash); // 所有大于 hash 的节点 Long key = tailMap.isEmpty() ? virtualNodes.firstKey() : tailMap.firstKey(); return virtualNodes.get(key); } // 统计对象与节点的映射关系 public void dumpObjectNodeMap(int objectMin, int objectMax) { // 统计 Map<String, Integer> objectNodeMap = new TreeMap<>(); // IP => COUNT for (int object = objectMin; object <= objectMax; ++object) { String nodeIp = getObjectNode(Integer.toString(object)); Integer count = objectNodeMap.get(nodeIp); objectNodeMap.put(nodeIp, (count == null ? 0 : count + 1)); } double totalCount = objectMax - objectMin + 1; for (Map.Entry<String, Integer> entry : objectNodeMap.entrySet()) { double percent = (100 * entry.getValue() / totalCount); System.out.println("IP=" + entry.getKey() + ": 命中率=" + percent + "%"); } } public static void main(String[] args) { ConsistentHash ch = new ConsistentHash(); ch.dumpObjectNodeMap( 0, 1000000); }}
运行
结果:
划线
评论
复制
发布于: 2020 年 07 月 08 日 阅读数: 24
L001
关注
还未添加个人签名 2018.04.28 加入
还未添加个人简介
评论