Java使用TreeMap实现一致性hash算法

关于一致性Hash算法原理可参考文章:一致性hash算法原理与实现

public class TreeMapConsistentHash {

    /**
     * 虚拟节点数量
     */
    private static final int VIRTUAL_NODE_SIZE = 4;

    /**
     * 定义treeMap
     */
    private TreeMap<Long, String> tree = new TreeMap<>();

    /**
     * 在服务器列表中根据key定位节点
     * @param values 服务器列表
     * @param key token
     * @return
     */
    public String choose(List<String> values, String key) {
        for (String value: values) {
           //value作为key,hash值作为value
            add(hash(value), value);
        }

        return selectNode(key);
    }

    /**
     * hash落环,并加入虚拟节点
     * @param key
     * @param value
     */
    private void add(long key, String value) {
        tree.clear();
        //虚拟节点
        for (int i = 0; i < VIRTUAL_NODE_SIZE; i++) {
            Long hash = this.hash("vir" + key + i);
            tree.put(hash, value);
        }
        tree.put(key, value);
    }

    /**
     * 在环中根据传入的值找到第一个server
     * 使用tailMap特性模拟hash环,如果tailMap返回空,则表示已经到了hash环的末尾,那么需要使用第一个key
     * @param value
     * @return
     */
    private String selectNode(String value) {
        long hash = hash(value);
        SortedMap<Long, String> after = tree.tailMap(hash);
        if (after != null && !after.isEmpty()) {

            String server = after.get(after.firstKey());
            System.out.println("路由成功:value: " + value + ", route server: " + server );
            return server;
        }
        return tree.firstEntry().getValue();
    }

    /**
     * hash计算
     * @param value
     * @return
     */
    private Long hash(String value) {
        byte[] digest = DigestUtils.md5(value);

        // hash code, Truncate to 32-bits
        long hashCode = ((long) (digest[3] & 0xFF) << 24) | ((long) (digest[2] & 0xFF) << 16) | ((long) (digest[1] & 0xFF) << 8) | (digest[0] & 0xFF);

        long truncateHashCode = hashCode & 0xffffffffL;
        return truncateHashCode;
    }
}

如何使用
比如我们使用zookeeper作为注册中心,那么将应用注册到zookeeper的特定节点下,取出节点下所有应用的服务地址,根据consumer方的
key hash值来选择具体调用那个provider

public class ConsistentHashRouter implements Router {

    private TreeMapConsistentHash hash = new TreeMapConsistentHash();

    /**
     * values: List<String> servers = Lists.newArrayList("127.0.0.1","192.168.11.1" ...)
     * key: consumer的特定数值,比如根据userId
     **/
    @Override
    public String chooseServer(List<String> values, String key) {
        return hash.choose(values,key);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。