浅析一致性哈希算法的原理及实现

Posted 噫!微斯人,吾谁与归

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析一致性哈希算法的原理及实现相关的知识,希望对你有一定的参考价值。

1.分布式缓存问题


以上是单节点环境下,但随着流量的增大,可能就演变为了如下情形:

这个负载均衡算法该如何设计最为合理呢?
首先能想到的最简单的方法可能就是随机或者轮询,这样会产生两个问题:一是数据冗余;二是数据可能已经被缓存,但请求却命中了不存在该数据的节点上。

如何解决这个问题?只需要保证相同的key被发送给相同节点上即可。再一想这不就是hash算法嘛【index = hash(key) % n】(n为节点的数量)

public class SimpleHash 

    public int loadBalance(String key) 
        return hash(key) % 3;
    
    private int hash(String key) 
        int hash = Math.abs(key.hashCode());
        .....
        .....
        return hash;
    

这种算法它的容错性和扩展性不是很好;一旦某个节点宕机或者加入新的节点时,导致n发生了变化,需要重新hash计算,这样可能导致大量缓存不命中,一瞬间给磁盘数据库造成了很大的压力。

容错性是指当某个节点宕机时,整个系统是否可以继续高效运行;扩展性是指加入新节点时,整个系统是否可以高效运行。

所以这种简单的哈希算法并不适用于实际场景,而本文所讲的一致性哈希算法解决了大量哈希重定位的问题。

2.一致性哈希算法

一致性哈希引入了一个虚拟的圆环,这个圆环有2^32个节点组成(0~ 2^32);

📚它的原理如下:

(1)对每个缓存服务器的IP作为key进行哈希计算,得到的结果一定分布在环上。
(2)对每个数据作为key进行哈希计算,得到的结果也一定分布在环上


按照顺时针,第一台遇到的节点就是该数据定位到的服务器。

❓当节点宕机或者添加新的节点时,它会出现什么样的结果呢?

public class ConsistentHash 
    private static final String[] NODES = "123.23.34.1", "123.52.2.1", "43.122.54.1";
    //模拟环形哈希表
    private static final SortedMap<Integer, String> CIRCLE_Map = new TreeMap<>();
    static 
        for (String node : NODES) 
            int index = hash(node);
            System.out.println(node + "节点的哈希值为:" + index);
            CIRCLE_Map.put(index, node);
        
    
    public static String loadBalance(String key) 
        int index2 = hash(key);
        //返回一个大于或等于index2的map
        SortedMap<Integer, String> tailMap = CIRCLE_Map.tailMap(index2);
        //如果tailMap为空,则直接返回哈希表的第一个数据
        if (tailMap.isEmpty()) 
            return CIRCLE_Map.get(CIRCLE_Map.firstKey());
         else 
            //第一个Key就是顺时针过去离node最近的那个结点
            return CIRCLE_Map.get(tailMap.firstKey());
        
    
    private static int hash(String key) 
        ........
        ........
    

    public static void main(String[] args) 
        System.out.println("zsh被路由到的节点为:" + loadBalance("zsh"));
    

此时可以看到只有一小部分数据进行了重定位,所以它具有很好的容错性和扩展性,❓那么它就没一点问题吗?答案肯定不是的,在某种情况下,会出现节点倾斜的问题。


当节点2宕机之后,数据1和数据2都重定位到了节点3上,节点分布式不均匀会导致数据倾斜的问题

3.引入虚拟节点

解决数据倾斜问题,可以通过增加大量节点使其分布均匀;但是实际上不可行,太浪费钱。所以引入虚拟节点,并将虚拟机节点定位到某个物理节点上即可。

如下图引入v1~v6虚拟节点,并建立与物理节点的映射关系;如定位到v1和v2的数据均定位到节点1上。


带虚拟节点的哈希算法实现

public cl

以上是关于浅析一致性哈希算法的原理及实现的主要内容,如果未能解决你的问题,请参考以下文章

浅析一致性哈希算法的原理及实现

一致性哈希(Consistent Hashing)算法的原理与实现

浅析分布式缓存弹性扩容下的一致性哈希算法

一致性哈希算法的应用及实现

最通俗易懂的一致性哈希算法原理

面经zhi一致性哈希算法原理及应用