数据结构与算法第十六讲:分布式算法之一致性Hash算法

简介: 数据结构与算法第十六讲:分布式算法之一致性Hash算法

1、为什么引入一致性hash算法

在分布式集群中,对机器的添加删除,或者机器故障后自动脱离集群 这些操作是分布式集群管理最基本的功能。如果采用常用的hash(object)%N算法,那么在有机器添加或者删除后,很多原有的数据就无法找到了,这样严重的违反了单调性原则

2、一致性Hash算法简介

一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得分布式哈希(DHT)可以在P2P环境中真正得到应用。

一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义:

  • 平衡性(Balance): 平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。
  • 单调性(Monotonicity): 单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
  • 分散性(Spread): 在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性
  • 负载(Load): 负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

3、一致性Hash算法

3.1、Hash环

使用常见的hash算法可以把一个key值哈希到一个具有2^32个桶的空间中。也可以理解成,将key值哈希到 [0, 2^32) 的一个数字空间中。 我们假设这个是个首尾连接的环形空间。如下图:

假设我们现在有key1,key2,key3,key4 4个key值,我们通过一定的hash算法,将其对应到上面的环形hash空间中。

k1=hash(key1);
k2=hash(key2);
k3=hash(key3);
k4=hash(key4);

同样的,假设我们有3台cache服务器,把缓存服务器通过hash算法,加入到上述的环中。一般情况下是根据机器的IP地址或者唯一的计算机别名进行哈希。

c1=hash(cache1);
c2=hash(cache2);
c3=hash(cache3);

接下来就是数据如何存储到cache服务器上了,key值哈希之后的结果顺时针找上述环形hash空间中,距离自己最近的机器节点,然后将数据存储到上面, 如上图所示,k1 存储到 c3 服务器上, k4,k3存储到c1服务器上, k2存储在c2服务器上。用图表示如下:

3.2、删除节点

假设cache3服务器宕机,这时候需要从集群中将其摘除。那么,之前存储再c3上的k1,将会顺时针寻找距离它最近的一个节点,也就是c1节点,这样,k1就会存储到c1上了,看下面的图,比较清晰。

摘除c3节点之后,只影响到了原先存储再c3上的k1,而k3、k4、k2都没有受到影响,也就意味着解决了最开始的解决方案(hash(key)%N)中可能带来的雪崩问题。

3.3、增加节点

新增C4节点之后,原先存储到C1的k4,迁移到了C4,分担了C1上的存储压力和流量压力。

3.4、不平衡的问题

上面的简单的一致性hash的方案在某些情况下但依旧存在问题: 一个节点宕机之后,数据需要落到距离他最近的节点上,会导致下个节点的压力突然增大,可能导致雪崩,整个服务挂掉

如下图所示:

当节点C3摘除之后,之前再C3上的k1就要迁移到C1上,这时候带来了两部分的压力:

  • 之前请求到C3上的流量转嫁到了C1上,会导致C1的流量增加,如果之前C3上存在热点数据,则可能导致C1扛不住压力挂掉。
  • 之前存储到C3上的key值转义到了C1,会导致C1的内容占用量增加,可能存在瓶颈。

当上面两个压力发生的时候,可能导致C1节点也宕机了。那么压力便会传递到C2上,又出现了类似滚雪球的情况,服务压力出现了雪崩,导致整个服务不可用。这一点违背了最开始提到的四个原则中的 平衡性, 节点宕机之后,流量及内存的分配方式打破了原有的平衡。

3.5、虚拟节点

“虚拟节点”( virtual node )是实际节点(机器)在 hash 空间的复制品( replica ),一实际个节点(机器)对应了若干个“虚拟节点”,这个对应个数也成为“复制个数”,“虚拟节点”在 hash 空间中以hash值排列。

依旧用图片来解释,假设存在以下的真实节点和虚拟节点的对应关系。

Visual100—> Real1
Visual101—> Real1
Visual200—> Real2
Visual201—> Real2
Visual300—> Real3
Visual301—> Real3

同样的,hash之后的结果如下:

hash(Visual100)—> V100  —> Real1
hash(Visual101)—> V101  —> Real1
hash(Visual200)—> V200  —> Real2
hash(Visual201)—> V201  —> Real2
hash(Visual300)—> V300  —> Real3
hash(Visual301)—> V301  —> Real3

key值的hash结果如上,这里暂时不写了。

和之前介绍的不添加虚拟节点的类似,主要聊下如果宕机之后的情况。

假设Real1机器宕机,则会发生一下情况。

  • 原先存储在虚拟节点V100上的k1数据将迁移到V301上,也就意味着迁移到了Real3机器上。
  • 原先存储再虚拟节点V101上的k4数据将迁移到V200上,也就意味着迁移到了Real2机器上。

结果如下图:

这个就解决之前的问题了,某个节点宕机之后,存储及流量压力并没有全部转移到某台机器上,而是分散到了多台节点上。解决了节点宕机可能存在的雪崩问题。

当物理节点多的时候,虚拟节点多,这个的雪崩可能就越小。

4、一致性Hash的应用

4.1、在Redis集群中扩容

使用场景

  • Redis 扩容

使用一致性hash的原因?

  • 当业务发展,网站缓存服务需要扩容时就会出现问题,比如3台缓存服务器要扩容到4台,会导致75%的数据无法命中

一致性hash算法是用于解决集群的伸缩性问题

  • 算法原理是:构造一个长度为2^32的整数环,根据节点名的hash值将缓存服务器节点放置在这个环上,然后计算要缓存数据的key的hash值,顺时针找到最近的服务器节点,将数据放到该服务器上。当服务器集群扩容时,3台扩容到4台,按照一致性hash算法,数据命中率高达75%。

4.2、在dubbo中做负载均衡

todo

5、参考文章

相关文章
|
2天前
|
存储 缓存 负载均衡
一致性哈希:解决分布式难题的神奇密钥
一致哈希是一种特殊的哈希算法,用于分布式系统中实现数据的高效、均衡分布。它通过将节点和数据映射到一个虚拟环上,确保在节点增减时只需重定位少量数据,从而提供良好的负载均衡、高扩展性和容错性。相比传统取模方法,一致性哈希能显著减少数据迁移成本,广泛应用于分布式缓存、存储、数据库及微服务架构中,有效提升系统的稳定性和性能。
11 1
|
1月前
|
算法 关系型数据库 MySQL
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
在分布式系统中,确保每个节点生成的 ID 唯一且高效至关重要。Snowflake 算法由 Twitter 开发,通过 64 位 long 型数字生成全局唯一 ID,包括 1 位标识位、41 位时间戳、10 位机器 ID 和 12 位序列号。该算法具备全局唯一性、递增性、高可用性和高性能,适用于高并发场景,如电商促销时的大量订单生成。本文介绍了使用 Go 语言的 `bwmarrin/snowflake` 和 `sony/sonyflake` 库实现 Snowflake 算法的方法。
46 1
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
|
14天前
|
存储 算法 安全
分布式系统架构1:共识算法Paxos
本文介绍了分布式系统中实现数据一致性的重要算法——Paxos及其改进版Multi Paxos。Paxos算法由Leslie Lamport提出,旨在解决分布式环境下的共识问题,通过提案节点、决策节点和记录节点的协作,确保数据在多台机器间的一致性和可用性。Multi Paxos通过引入主节点选举机制,优化了基本Paxos的效率,减少了网络通信次数,提高了系统的性能和可靠性。文中还简要讨论了数据复制的安全性和一致性保障措施。
32 1
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
40 5
|
1月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
2月前
|
算法
基于粒子群算法的分布式电源配电网重构优化matlab仿真
本研究利用粒子群算法(PSO)优化分布式电源配电网重构,通过Matlab仿真验证优化效果,对比重构前后的节点电压、网损、负荷均衡度、电压偏离及线路传输功率,并记录开关状态变化。PSO算法通过迭代更新粒子位置寻找最优解,旨在最小化网络损耗并提升供电可靠性。仿真结果显示优化后各项指标均有显著改善。
|
2月前
|
消息中间件 缓存 算法
分布式系列第一弹:分布式一致性!
分布式系列第一弹:分布式一致性!
|
2月前
|
算法 Java 关系型数据库
漫谈分布式数据复制和一致性!
漫谈分布式数据复制和一致性!
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
187 9
|
1月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
32 1