一致性哈希算法的理解

概念

一致性哈希算法及其在分佈式系統中的應用

http://blog.codinglabs.org/articles/consistent-hashing.html

簡單總結:

普通分佈式緩存痛點:服務器宕機或擴容,數據重新hash計算影響大。

虛擬環:一致性hash算法是來做服務器的負載均衡,而服務器的IP地址是32位,所以是2^32-1次方的數值空間。

服務器尋址:h = Hash(ip或主機名) ,放入服務虛擬環中

數據定位服務器:採用服務器尋址相同算法h = Hash(i數據key) % N,數據順時針遇到的第一臺服務器

宕機容錯:隻影響此服務器環空間前一臺服務器(逆時針)的數據,數據重新hash計算定位即可

增加機器可擴展:隻影響新服務器環空間前一臺服務器(逆時針)的數據,數據重新hash計算定位即可

數據傾斜:虛擬節點解決,即服務節點計算多個哈希,每個計算結果位置都放置一個此服務節點。

圖例:

例子:

數據結構:採用SortedMap,SortedMap<Long, T> circle = new TreeMap<Long, T>(),用到的方法如圖紅框所示,如果數據key的hash值不再服務虛擬環節點上,那麼使用tailMap(數據key的hash值)查找大於key的hash值的所有數據,然後使用firstKey找到相鄰的第一個健key,在由服務虛擬環節點獲取服務節點,存儲數據

代碼例子:

private final Hashing hash;// hash算法
private final int virtualNodeNum;// 虛擬績點
private final SortedMap<Long, T> circle = new TreeMap<Long, T>();// 服務節點hash環

public ConsistentHash(Hashing hash, int virtualNodeNum, Collection<T> nodes) {
    this.hash = hash;
    this.virtualNodeNum = virtualNodeNum;
    for (T node : nodes) {
        add(node);
    }
}
    /**
     * 增加機器節點
     *
     * @param node
     */
    public void add(T node) {
        for (int i = 0; i < this.virtualNodeNum; i++) {
            circle.put(this.hash.hash(node.toString() + i), node);
        }
    }
    /**
     * 取得真實機器節點
     * key: 數據key
     */
    public T get(String key) {
        if (circle.isEmpty()) {
            return null;
        }
        // 獲取hash值
        long hash = this.hash.hash(key);
        if (!circle.containsKey(hash)) {
            // 沿環的順時針找到大於hash值的所有虛擬節點
            SortedMap<Long, T> tailMap = circle.tailMap(hash);
            // 用得到的所有虛擬節點判斷是否爲空,空則找到第一個機器節點,否則返回第一個節點
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        // 返回該虛擬節點對應的機器節點的信息
        return circle.get(hash);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章