GeekIBLi

分布式-一致性哈希算法

2021-07-28

一致性哈希算法

一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法,常用于负载均衡。Memcached client也选择这种算法,解决将key-

value均匀分配到众多Memcached server上的问题。它可以取代传统的取模操作,解决了取模操作无法应对增删Memcached Server的

问题(增删server会导致同一个key,在get操作时分配不到数据真正存储的server,命中率会急剧下降)。

哈希指标

评估一个哈希算法的优劣,有如下指标,而一致性哈希全部满足:

  • 均衡性(Balance):将关键字的哈希地址均匀地分布在地址空间中,使地址空间得到充分利用,这是设计哈希的一个基本特性。

  • 单调性(Monotonicity): 单调性是指当地址空间增大时,通过哈希函数所得到的关键字的哈希地址也能映射的新的地址空间,而不是仅

    限于原先的地址空间。或等地址空间减少时,也是只能映射到有效的地址空间中。简单的哈希函数往往不能满足此性质。

  • 分散性(Spread): 哈希经常用在分布式环境中,终端用户通过哈希函数将自己的内容存到不同的缓冲区。此时,终端有可能看不到所

    有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不

    同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为

    它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够

    尽量避免不一致的情况发生,也就是尽量降低分散性。

  • 负载(Load): 负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于

    一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能

    够尽量降低缓冲的负荷

一致性哈希

将节点通过hash映射到hash环上,理想的情况是多个节点直接分布均匀

当我们的对象通过hash算法分配在hash环上的时候,它是固定分配到一个节点的空间上的,当我们在BC之间插入一个节点时,仅仅会影

响到BC这一段空间上的数据,而不是整个环上的数据都要跟着变化;

现实情况下,节点之间可能分配不均匀

这和传统的hash取模一样,同样会数据倾斜的问题!

虚拟节点

这个时候虚拟节点就此诞生,下面让我们来看一下虚拟节点在一致性Hash中的作用。当我们在Hash环上新增若干个点,那么每个点之间

的距离就会接近相等。按照这个思路我们可以新增若干个片/表,但是成本有限,我们通过复制多个A、B、C的副本({A1-An},{B1-Bn},{C1-

Cn})一起参与计算,按照顺时针的方向进行数据分布,按照下图示意:

此时A=[A,C1)&[A1,C2)&[A2,B4)&[A3,A4)&[A4,B1);B=[B,A1)&[B2,C)&[B3,C3)&[B4,C4)&[B1,A);C=[C1,B)&[C2,B2)&[C,B3)&[B3,C3)&

[C4,A3);由图可以看出分布点越密集,平衡性约好。

算法实现

一致性哈希算法有多种具体的实现,包括 Chord 算法,KAD 算法等,都比较复杂。

参考资料

1 、一致性哈希算法的原理与实现
2、浅谈一致性Hash原理及应用
3、https://juejin.cn/post/6844903598694858766