一致性哈希算法的理解

概念

一致性哈希算法及其在分布式系统中的应用

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);
    }

 

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