哈希一致性详解

  • 一致性哈希是什么,使用场景,解决了什么问题?

    • 如何分配请求

      • 大多数网站背后肯定不是只有一台服务器提供服务,因为单机的并发量和数据量都是有限的,所以都会用多台服务器构成集群来对外提供服务。

      • 现在有那么多个节点(后面统称服务器为节点,因为少一个字),要如何分配客户端的请求呢?

        • 「负载均衡问题」解决方法

          • 引入一个中间的负载均衡层,让它将外界的请求「轮流」的转发给内部的集群。

          • 每个节点的硬件配置有所区别,我们可以引入权重值,将硬件配置更好的节点的权重值设高,然后根据各个节点的权重值,按照一定比重分配在不同的节点上,让硬件配置更好的节点承担更多的请求,这种算法叫做加权轮询

            • 使用场景是建立在每个节点存储的数据都是相同的前提。所以,每次读数据的请求,访问任意一个节点都能得到结果。

            • 加权轮询算法是无法应对「分布式系统(数据分片的系统)」的,因为分布式系统中,每个节点存储的数据是不同的。

    • 使用哈希算法有什么问题

      • 哈希算法。因为对同一个关键字进行哈希计算,每次计算都是相同的值,这样就可以将某个 key 确定到一个节点了,可以满足分布式系统的负载均衡需求。

      • 哈希算法最简单的做法就是进行取模运算

      • 很致命的问题,如果节点数量发生了变化,也就是在对系统做扩容或者缩容时,必须迁移改变了映射关系的数据

      • 假设总数据条数为 M,哈希算法在面对节点数量变化时,最坏情况下所有数据都需要迁移,所以它的数据迁移规模是 O(M),这样数据的迁移成本太高了。

    • 使用一致性哈希算法有什么问题

      • 一致哈希算法也用了取模运算,但与哈希算法不同的是,哈希算法是对节点的数量进行取模运算,而一致哈希算法是对 2^32 进行取模运算,是一个固定的值。

      • 把一致哈希算法是对 2^32 进行取模运算的结果值组织成一个圆环

      • 一致性哈希要进行两步哈希:

        • 第一步:对存储节点进行哈希计算,也就是对存储节点做哈希映射,比如根据节点的 IP 地址进行哈希;

        • 第二步:当对数据进行存储或访问时,对数据进行哈希映射;

      • 一致性哈希是指将「存储节点」和「数据」都映射到一个首尾相连的哈希环上。

      • 对「数据」进行哈希映射得到一个结果要怎么找到存储该数据的节点呢?

        • 答案是,映射的结果值往顺时针的方向的找到第一个节点,就是存储该数据的节点。

        • 对要查询的 key-01 进行哈希计算,确定此 key-01 映射在哈希环的位置,然后从这个位置往顺时针的方向找到第一个节点,就是存储该 key-01 数据的节点。

        • 当需要对指定 key 的值进行读写的时候,要通过下面 2 步进行寻址:

          • 对 key 进行哈希计算,确定此 key 在环上的位置;

          • 从这个位置沿着顺时针方向走,遇到的第一节点就是存储 key 的节点

      • 在一致哈希算法中,如果增加或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。

      • 一致性哈希算法并不保证节点能够在哈希环上分布均匀,这样就会带来一个问题,会有大量的请求集中在一个节点上。

      • 在这种节点分布不均匀的情况下,进行容灾与扩容时,哈希环上的相邻节点容易受到过大影响,容易发生雪崩式的连锁反应。

      • 一致性哈希算法虽然减少了数据迁移量,但是存在节点分布不均匀的问题。

    • 如何通过虚拟节点提高均衡度

      • 加入虚拟节点,也就是对一个真实节点做多个副本。

      • 不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点,所以这里有「两层」映射关系。

      • 虚拟节点除了会提高节点的均衡度,还会提高系统的稳定性。当节点变化时,会有不同的节点共同分担系统的变化,因此稳定性更高。

      • 带虚拟节点的一致性哈希方法不仅适合硬件配置不同的节点的场景,而且适合节点规模会发生变化的场景

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EqualsAndHashCode 是 Java 中的两个常用方法,用来比较对象的相等性和生成对象的哈码。 equals() 方法用于判断两个对象是否相等。在默认情况下,它比较的是两个对象的引用是否相同,即比较对象的内存地址。如果我们望比较对象的内容是否相等,就需要重写 equals() 方法。重写时需要遵循一些规则: - 自反性:一个对象必须和自身相等,即 x.equals(x) 应返回 true。 - 对称性:如果 x.equals(y) 返回 true,那么 y.equals(x) 也应返回 true。 - 传递性:如果 x.equals(y) 和 y.equals(z) 都返回 true,那么 x.equals(z) 也应返回 true。 - 一致性:如果对象没有被修改,多次调用 equals() 应返回相同的结果。 - 非空性:任何非空引用 x 调用 x.equals(null) 应返回 false。 hashCode() 方法用于计算对象的哈码。哈码是一个整数,常用于数据结构中的散列算法。在一些集合类中(如 HashMap、HashSet),hashCode() 方法用于确定对象在集合中的存储位置。在重写 equals() 方法时,也需要同时重写 hashCode() 方法,以保证相等的对象具有相同的哈码。 在重写 hashCode() 方法时,需要遵循以下规则: - 如果两个对象通过 equals() 方法相等,那么它们的 hashCode() 值必须相等。 - 如果两个对象的 hashCode() 值相等,它们并不一定相等。 在实际重写 equals() 和 hashCode() 方法时,需要根据对象的实际情况确定比较的字段,通常是对象的属性值。还需要使用 instanceof 运算符检查参数类型,并进行类型转换。同时,equals() 和 hashCode() 方法应尽量保持一致性,即所比较的字段应该一致。 以上是 EqualsAndHashCode 方法的详解望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值