Java使用TreeMap實(shí)現(xiàn)一致性hash算法

關(guān)于一致性Hash算法原理可參考文章:一致性hash算法原理與實(shí)現(xiàn)

public class TreeMapConsistentHash {

    /**
     * 虛擬節(jié)點(diǎn)數(shù)量
     */
    private static final int VIRTUAL_NODE_SIZE = 4;

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

    /**
     * 在服務(wù)器列表中根據(jù)key定位節(jié)點(diǎn)
     * @param values 服務(wù)器列表
     * @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落環(huán),并加入虛擬節(jié)點(diǎn)
     * @param key
     * @param value
     */
    private void add(long key, String value) {
        tree.clear();
        //虛擬節(jié)點(diǎn)
        for (int i = 0; i < VIRTUAL_NODE_SIZE; i++) {
            Long hash = this.hash("vir" + key + i);
            tree.put(hash, value);
        }
        tree.put(key, value);
    }

    /**
     * 在環(huán)中根據(jù)傳入的值找到第一個(gè)server
     * 使用tailMap特性模擬hash環(huán),如果tailMap返回空,則表示已經(jīng)到了hash環(huán)的末尾,那么需要使用第一個(gè)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計(jì)算
     * @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作為注冊(cè)中心,那么將應(yīng)用注冊(cè)到zookeeper的特定節(jié)點(diǎn)下,取出節(jié)點(diǎn)下所有應(yīng)用的服務(wù)地址,根據(jù)consumer方的
key hash值來(lái)選擇具體調(diào)用那個(gè)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的特定數(shù)值,比如根據(jù)userId
     **/
    @Override
    public String chooseServer(List<String> values, String key) {
        return hash.choose(values,key);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容