负载均衡——一致性哈希算法

不加虚拟节点的

在这里插入图片描述

加虚拟节点的

在这里插入图片描述

一致性哈希算法的优势

使用:hash(key)%容器,如果加入或者删除节点,会将所有key对应的服务器重新排序。
一致性哈希算法使用TreeMap来实现,当由节点加入或者删除时,只会影响一小部分。

原理

物理节点和虚拟节点

物理节点是物理机的地址,一个物理节点可以对应多个虚拟节点。
当一个物理节点退出系统时,其所有虚拟节点也会从哈希环中被移除。

虚拟节点的作用:

  1. 更均匀的数据分布
  2. 动态平衡负载,对于性能更强的物理节点,可以增加其虚拟节点的数量,让其承担更多的数据负载

通过TreeMap来实现一致性哈希算法的实践

虚拟节点:是通过key为虚拟节点的位置,而value为真实的物理节点来实现。

public class ConsistentHashing {

    private final TreeMap<Long, String> circle = new TreeMap<>();
    private final int numberOfReplicas;//每个物理节点的虚拟节点数量

    public ConsistentHashing(int numberOfReplicas) {
        this.numberOfReplicas = numberOfReplicas;
    }

    // 添加一个节点
    public void addNode(String node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            long hash = hash(node + i);
            circle.put(hash, node);
        }
    }

    // 移除一个节点
    public void removeNode(String node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            long hash = hash(node + i);
            circle.remove(hash);
        }
    }

    // 获取一个节点
    public String getNode(String key) {
        if (circle.isEmpty()) {
            return null;
        }
        long hash = hash(key);
        if (!circle.containsKey(hash)) {
            SortedMap<Long, String> tailMap = circle.tailMap(hash);
            hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        }
        return circle.get(hash);
    }

    // 计算哈希值
    private long hash(String key) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        byte[] bytes = md.digest(key.getBytes(StandardCharsets.UTF_8));
        return ((long) (bytes[0] & 0xFF) << 56)
                | ((long) (bytes[1] & 0xFF) << 48)
                | ((long) (bytes[2] & 0xFF) << 40)
                | ((long) (bytes[3] & 0xFF) << 32)
                | ((long) (bytes[4] & 0xFF) << 24)
                | ((long) (bytes[5] & 0xFF) << 16)
                | ((long) (bytes[6] & 0xFF) << 8)
                | ((long) (bytes[7] & 0xFF));
    }

    public static void main(String[] args) {
        ConsistentHashing consistentHashing = new ConsistentHashing(3);
        
        consistentHashing.addNode("NodeA");
        consistentHashing.addNode("NodeB");
        consistentHashing.addNode("NodeC");

        System.out.println("Key1 is mapped to " + consistentHashing.getNode("Key1"));
        System.out.println("Key2 is mapped to " + consistentHashing.getNode("Key2"));
        System.out.println("Key3 is mapped to " + consistentHashing.getNode("Key3"));

        consistentHashing.removeNode("NodeB");

        System.out.println("After removing NodeB:");
        System.out.println("Key1 is mapped to " + consistentHashing.getNode("Key1"));
        System.out.println("Key2 is mapped to " + consistentHashing.getNode("Key2"));
        System.out.println("Key3 is mapped to " + consistentHashing.getNode("Key3"));
    }
}
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值