一致性hash负载均衡

这篇具有很好参考价值的文章主要介绍了一致性hash负载均衡。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Hash算法的问题

今天看下一致性hash,常见的负载均衡可能使用过hash,比如nginx中,如果使用session最简单就是通过hash,比如根据用户的请求ip进行hash,让不同用户的请求打到同一台服务器,这样状态处理起来最简单,对于session来说,如果现在重新上线了一台服务器,导致了所有请求hash之后的得到的服务器地址变了,也就是session可能全部丢失了,即使用户对应的服务器并没有重启,但是因为服务器数量发生了变化,导致分配到的服务器有所改变,这就是hash带来的问题。

一致性hash的使用场景

那么一致性hash就是解决hash的这些问题诞生的,一致性hash常见的落地场景可以想象下redis的数据,redis是设计了16384的hash槽,每个数据来的根据key做hash,然后分配到固定的hash槽,redis需要集群分片的时候不具体区分每一个key,是去分hash槽,然后新增节点的之后只需要分配给其一些hash槽,然后转移对应的数据过去即可,删除节点的时候也是,只需要把这个节点的数据分配给其他节点即可,没涉及到的数据不会有影响。

一致性hash概念

所以一致性hash的定义也就是,我先分配很多的hash节点,然后我每一个实际的提供服务的节点,负责一部分的hash节点,hash节点是固定的(比实际节点大很多),然后上下线节点只需要调整实际节点负责的节点数量即可。
实际大家说的hash环的问题,就是说,我的很多虚拟节点(hash节点)组成的环,然后让实际的提供服务的节点尽量均匀的落到hash节点上,后续的请求或者说数据,按照hash之后也落到虚拟hash节点上,这个节点可能并没有实际的服务节点,他就可以向后遍历找到对应提供服务的节点,也就代表着一个实际提供服务的节点负责他前面的所有虚拟节点,直到遇到上一个实际服务的节点。

一致性hash需要处理的问题

这样可能存在的问题就是实际服务提供者的hash结果倾斜怎么办,也就是所有节点都落到一片去了,这样前面的节点就需要负责绝大部分的请求,还是要想办法让其尽量均匀,也就是要给每个实际节点,可以多种hash算法,生成多个节点,让其尽可能均匀的分布到环上,让请求均匀分配到节点上
来看下dubbo怎么具体实现的这个问题,关键代码如下:

        ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
            // treeMap方便向上取
            this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
            this.identityHashCode = identityHashCode;
            URL url = invokers.get(0).getUrl();
            // 虚拟节点数量?默认160,这里是一个服务虚拟出来的节点
            this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160);
            String[] index = COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, "0"));
            argumentIndex = new int[index.length];
            for (int i = 0; i < index.length; i++) {
                argumentIndex[i] = Integer.parseInt(index[i]);
            }
            for (Invoker<T> invoker : invokers) {
                String address = invoker.getUrl().getAddress();
                for (int i = 0; i < replicaNumber / 4; i++) {
                    // 这里也就是一个服务默认先虚拟160个节点
                    byte[] digest = Bytes.getMD5(address + i);
                    for (int h = 0; h < 4; h++) {
                        // 分别4位,4位的进行运算,也就是放四个值,每个invoker,使用不同位数得到的hash值
                        long m = hash(digest, h);
                        virtualInvokers.put(m, invoker);
                    }
                }
            }
        }
    	// hash算法,对其每一位进行处理,想要均匀
        private long hash(byte[] digest, int number) {
            return (((long) (digest[3 + number * 4] & 0xFF) << 24)
                    | ((long) (digest[2 + number * 4] & 0xFF) << 16)
                    | ((long) (digest[1 + number * 4] & 0xFF) << 8)
                    | (digest[number * 4] & 0xFF))
                    & 0xFFFFFFFFL;
        }
    	// 具体的选择算法,也就是hash结果选择,关键结构逻辑参考构造方法
        public Invoker<T> select(Invocation invocation) {
            byte[] digest = Bytes.getMD5(RpcUtils.getMethodName(invocation));
            return selectForKey(hash(digest, 0));
        }
    	// 具体的选择方法
        private Invoker<T> selectForKey(long hash) {
            // 向上取,TreeMap的方法
            Map.Entry<Long, Invoker<T>> entry = virtualInvokers.ceilingEntry(hash);
            if (entry == null) {
                // 没取到的取第一个,也就是造成一个环的概念,数据落到最后一个节点后面
                entry = virtualInvokers.firstEntry();
            }
            return entry.getValue();
        }

总结

可以看到dubbo为了处理数据倾斜的问题,默认虚拟160个节点,然后根据地址加上对应的值,然后又采用每一位数字的hash算法进行散列,得到的值,采用的数据结构就是TreeMap,是一个可排序的Map,可以直接向上取,ceilingEntry,数据过来之后hash得到值,然后取对应的节点,TreeMap兼具一定的查找性能能文章来源地址https://www.toymoban.com/news/detail-714212.html

到了这里,关于一致性hash负载均衡的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 区块链:哈希算法与一致性哈希算法

    本篇主要介绍区块链中常用到的哈希算法。 1 哈希算法 1.1 定义及特性   哈希算法是指通过哈希函数(Hash Function)对任意长度的输入数据(比如文件、消息、数字等)进行转换,生成一个固定长度的哈希值(Hash Value)的过程。   在区块链中,哈希算法常用于区块验证及安全性保

    2024年02月17日
    浏览(51)
  • Redis扩容与一致性Hash算法解析

    作者:zhaokk 在分布式系统中,随着数据量的增加和负载的变化,对于存储系统的扩容变得尤为重要。Redis作为一种高性能的内存数据库,其在扩容方面采用了一致性Hash算法,以实现无缝的数据分布和负载均衡。本篇博客将详细探讨Redis的扩容机制,同时深入解析一致性Hash算法

    2024年02月12日
    浏览(39)
  • 谈谈一致性哈希算法

    一致性哈希算法是1997年由麻省理工的几位学者提出的用于解决分布式缓存中的热点问题。大家有没有发现,我们之前介绍的例如快排之类的算法是更早的六七十年代,此时分布式还没有发展起来, 大家往往还在提高单机性能。但是九十年代开始,逐渐需要用分布式集群来解

    2024年02月07日
    浏览(39)
  • 07. 算法之一致性哈希算法介绍

    哈希算法在程序开发中的很多地方都能看到他的身影,但是哈希有他的局限性,比如如果两个key哈希到同一个位置的时候,此时就不好处理。本节我们介绍一下常规处理方式。 哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。

    2024年02月06日
    浏览(40)
  • 详解一致性hash算法(Consistent-hashing):原理、图解、代码示例

    Consistent hashing is a scheme that provides hash table functionality in a way that the addition or removal of one slot does not significantly change the mapping of keys to slots. Hash算法是一种将任意长度的消息压缩到一个固定长度的输出(即哈希值)的算法。它主要用于数据完整性校验、数据加密、数字签名等方面

    2024年02月07日
    浏览(37)
  • Ceph的crush算法与一致性hash对比介绍

    本文分享自天翼云开发者社区《Ceph的crush算法与一致性hash对比介绍》,作者:l****n 首先,我们先回顾下一致性hash以及其在经典存储系统中的应用。 一致性hash的基本原理 一致性hash的基本思想是,有一个hash函数,这个hash函数的值域形成了一个环(收尾相接:the largest hash value

    2024年04月23日
    浏览(22)
  • Python小知识 - 一致性哈希算法

    一致性哈希算法 一致性哈希算法(Consistent Hashing Algorithm)是用于解决分布式系统中节点增减比较频繁的问题。它的思想是,将数据映射到0~2^64-1的哈希空间中,并通过哈希函数对数据进行映射,计算出数据所在的节点。当节点增加或减少时,只需要重新计算数据所在的节点即

    2024年02月09日
    浏览(39)
  • 一致性哈希算法优势在哪?如何实现?

    1.1 简介Hash 哈希算法即散列算法,是一种从任意文件中创造小的数字「指纹」的方法。与指纹一样,散列算法就是一种以较短的信息来保证文件唯一性的标志,这种标志与文件的每一个字节都相关,而且难以找到逆向规律。因此,当原有文件发生改变时,其标志值也会发生改

    2024年02月03日
    浏览(42)
  • Redis扩容机制与一致性哈希算法解析

    在分布式系统设计中,Redis是一个备受欢迎的内存数据库,而一致性哈希算法则是分布式系统中常用的数据分片和负载均衡技术。本文将深入探讨Redis的扩容机制以及一致性哈希算法的原理,同时提供示例代码以帮助读者更好地理解这两个重要概念。 Redis是一种高性能的内存数

    2024年02月11日
    浏览(36)
  • 一文搞懂分库分表算法,通俗易懂(基因法、一致性 hash、时间维度)

    最近手上一个系统的访问速度有点慢,老早前用多线程优化过一些接口,将一些复杂 sql 改成单表查询,走内存处理,成功的将 一些 10 多秒的接口优化到 500 ms,但是数据量上来了单表查询效率也有点慢了,不得不考虑进行分库分表了,当然我这里只进行分表,没分库,问就是

    2024年02月03日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包