Week 5 命题作业
发布于: 2020 年 11 月 06 日
实现思路:
使用支持排序的 TreeMap 实现 Hash 环
使用 Java 原生的 Object.hashCode 获取 hashCode
每台服务器使用 50 个节点,三台服务器共 150 个节点(经验值?)
public class ConsistentHashUtils { /** * 服务器节点,应该从配置文件中取读 */ private static String[] servers = {"192.12.43.222", "44.36.14.25", "45.26.48.91"}; /** * 使用排序集合 TreeMap 实现 Hash 环 */ private static SortedMap<Long, String> hashRing = new TreeMap<>(); /** * 生成 Hash 环,并安放服务器节点及其虚拟节点。 * <p> * 1. 当服务器节点发生改变(增删改)时,需要重新生成 * 2. 服务器节点不变时,Hash 环也不能变,否则可能一个 key 每次分配到的服务器不一样 * 3. 这个方法应该是在程序启动时执行,且在服务器节点发生改变时,由专门的后台线程执行! */ public static void generateHashRing() { for (String server : servers) { // 把服务器及对应虚拟节点保存到 treeMap 中,也就是放到 hash 环上 // 这里每个服务器写死 49 个虚拟节点 for (int i = 0; i < 50; i++) { // 加上一个随机值,保证所有虚拟节点计算的 hash 值不同 long hashCode = getHashCode(server + UUID.randomUUID()); // 上环 hashRing.put(hashCode, server); } } } /** * 获取一致性 Hash 算法分配到的服务器节点 * * treeMap 按自然数从小到大排序,要找出第一个比 dataKey HashCode 大的服务器节点,也就是顺时针第一个, * 直接将 treeMap 从 dataKey HashCode 截断即可,然后有两种情况 * 1. 没有比它大的,则取整个 treeMap 的第一条数据 * 2. 否则,取截断后的第一条数据 * * @param dataKey key * @return 服务器节点 */ public static String getServerByConsistentHash(String dataKey) { String server; SortedMap<Long, String> tailMap = hashRing.tailMap(getHashCode(dataKey)); if (tailMap.isEmpty()) { server = hashRing.get(hashRing.firstKey()); } else { server = hashRing.get(tailMap.firstKey()); } return server; } /** * 获取字符串对应的 hashCode * * @param str 需要计算 Hash 的字符串 * @return hashCode */ private static long getHashCode(String str) { return Math.abs(str.hashCode()) << 2; } /** * 测试 */ public static void main(String[] args) { // 使用 Map 记录测试结果 Map<String, Integer> resultMap = new HashMap<>(); for (String server : servers) { resultMap.put(server, 0); } // 生成 Hash 环 generateHashRing(); // 测试 10 万条数据 for (int i = 0; i < 100000; i++) { String key = UUID.randomUUID().toString(); String server = getServerByConsistentHash(key); resultMap.put(server, resultMap.get(server) + 1); } resultMap.forEach((key, value) -> System.out.println(String.format("服务器 %s,分配到的数量:%d", key, value))); }}
测试结果:
服务器 44.36.14.25,分配到的数量:30640服务器 45.26.48.91,分配到的数量:35955服务器 192.12.43.222,分配到的数量:33405
划线
评论
复制
发布于: 2020 年 11 月 06 日阅读数: 21
balsamspear
关注
还未添加个人签名 2019.10.24 加入
还未添加个人简介
评论