数据结构——一致性哈希

一、概述

(1) 传统哈希(硬哈希)

        分布式系统中,假设有 n 个节点,传统方案使用 mod(key, n) 映射数据和节点。 
        当扩容或缩容时(哪怕只是增减1个节点),映射关系变为 mod(key, n+1) / mod(key, n-1),绝大多数数据的映射关系都会失效。

(2)一致性哈希(Consistent Hashing)
        1997年,麻省理工学院(MIT)的 David Karger 等6个人发布学术论文《Consistent hashing and random trees: distributed caching protocols for relieving hot spots on the World Wide Web(一致性哈希和随机树:用于缓解万维网上热点的分布式缓存协议)》,对于 K 个关键字和 n 个槽位(分布式系统中的节点)的哈希表,增减槽位后,平均只需对 K/n 个关键字重新映射。

(3) 哈希指标

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

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

                单调性(Monotonicity): 单调性是指当地址空间增大时,通过哈希函数所得到的关键字的哈希地址也能映射的新的地址空间,而不是仅限于原先的地址空间。或等地址空间减少时,也是只能映射到有效的地址空间中。简单的哈希函数往往不能满足此性质。

                分散性(Spread): 哈希经常用在分布式环境中,终端用户通过哈希函数将自己的内容存到不同的缓冲区。此时,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。

                负载(Load): 负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

二、算法原理

(1)映射方案


(2)公用哈希函数和哈希环
        设计哈希函数 Hash(key),要求取值范围为 [0, 2^32) 
        各哈希值在上图 Hash 环上的分布:时钟12点位置为0,按顺时针方向递增,临近12点的左侧位置为2^32-1。

(3) 节点(Node)映射至哈希环
        如图哈希环上的绿球所示,四个节点 Node A/B/C/D, 
        其 IP 地址或机器名,经过同一个 Hash() 计算的结果,映射到哈希环上。

(4)对象(Object)映射于哈希环
        如图哈希环上的黄球所示,四个对象 Object A/B/C/D, 
        其键值,经过同一个 Hash() 计算的结果,映射到哈希环上。

(5)对象(Object)映射至节点(Node)
        在对象和节点都映射至同一个哈希环之后,要确定某个对象映射至哪个节点, 
        只需从该对象开始,沿着哈希环顺时针方向查找,找到的第一个节点,即是。 
        可见,Object A/B/C/D 分别映射至 Node A/B/C/D。

(6)删除节点
        现实场景:服务器缩容时删除节点,或者有节点宕机。如下图,要删除节点 Node C: 
        只会影响欲删除节点(Node C)与上一个(顺时针为前进方向)节点(Node B)与之间的对象,也就是 Object C, 
        这些对象的映射关系,按照 2.1.4 的规则,调整映射至欲删除节点的下一个节点 Node D。 
其他对象的映射关系,都无需调整。 


(7)增加节点
        现实场景:服务器扩容时增加节点。比如要在 Node B/C 之间增加节点 Node X: 
        只会影响欲新增节点(Node X)与上一个(顺时针为前进方向)节点(Node B)与之间的对象,也就是 Object C, 
        这些对象的映射关系,按照 2.1.4 的规则,调整映射至新增的节点 Node X。 
        其他对象的映射关系,都无需调整。 


(8)虚拟节点
        对于前面的方案,节点数越少,越容易出现节点在哈希环上的分布不均匀,导致各节点映射的对象数量严重不均衡(数据倾斜);相反,节点数越多越密集,数据在哈希环上的分布就越均匀。 
        但实际部署的物理节点有限,我们可以用有限的物理节点,虚拟出足够多的虚拟节点(Virtual Node),最终达到数据在哈希环上均匀分布的效果: 
        如下图,实际只部署了2个节点 Node A/B, 
        每个节点都复制成3倍,结果看上去是部署了6个节点。 
        可以想象,当复制倍数为 2^32 时,就达到绝对的均匀,通常可取复制倍数为32或更高。 
        虚拟节点哈希值的计算方法调整为:对“节点的IP(或机器名)+虚拟节点的序号(1~N)”作哈希。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值