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

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thecoastlines

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值