一致性hash环原理

转自信仰《一致性hash环原理》(知乎)
吴帝永《一致性Hash算法(hash环)》

1. 为什么需要一致性Hash环

假设我们有N个Cache服务器的Node,我们的要求就是将key均分的存储到Cache节点上,经典的做法就是如下

position = hash(key) mod N

那么这样在如下两种情况下会出现问题:

  • 有一台机器挂了
  • 新增一台机器

这时候公式变成

position = hash(key) mod (N+1) position = hash(key) mod (N-1)

之前所有的求得结果都不对了,导致全部cache miss,只能回源到mysql,最终可想而知整个系统崩溃,如果这样设计分布式缓存系统,那这个分布式缓存系统是失败的。

2. 一致性hash算法的特性

  • 平衡性
    尽可能让数据尽可能分散到所有节点上,避免造成极其不均匀

  • 单调性
    要求在新增或者减少节点的时候,原有的结果绝大部分不受影响,而新增的数据尽可能分配到新加的节点

  • 分散性
    好的算法在不同终端,针对相同的数据的计算,得到的结果应该是一样的,一致性要很强

  • 负载
    针对相同的节点,避免被不同终端映射不同的内容,实际上是从另一个角度看待分散性问题。

  • 平滑性
    对于增加节点或者减少节点,应该能够平滑过渡

3. 一致性Hash算法原理介绍

3.1 背景

一致性哈希算法在1997年由MIT的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题。

3.2 算法原理

虚拟一个环的概念,在环上构造一个0~232-1的哈希值空间

将N台服务器节点计算Hash值,映射到这个环上。整个空间按顺时针方向组织。0和232-1在零点中方向重合。

可以用服务器的IP或者主机名作为关键字来计算hash值,从而确定其在哈希环上的位置,假设有三台服务器,使用ip地址哈希后在环空间的位置如下:
在这里插入图片描述
将数据用相同的Hash算法计算的值,映射到这个环上

如果服务器数量不多且个数相对稳定,我们也可以手动设置这些服务器的位置,如设A在230-1位置,B在231-1位置,C在3*230-1位置,D在232-1位置,则hash值为0~230-1的数据存储在A中,hash值为230-1~231-1的数据存储在B中,以此类推。

定位数据存储在哪台服务器的方法为:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。可以为这些服务器维护一条二分查找树,定位服务器的过程就是在二分查找树中找刚好比其大的节点。
在这里插入图片描述

  • d1,d2就存储到Node B
  • d3, d4, d5存储到Node C
  • d6, d7, d8存储到Node A

下面分析一致性哈希算法的容错性和可扩展性。
Node B宕机后,其他都不受影响,d1,d2会发生一次cache miss,然后再会存储Node C,影响比较小
在这里插入图片描述

如果新增加一台机器Node D,d6,d7就会存储到了Node D,不再存储到Node A
在这里插入图片描述

4. 一致性Hash节点太少改良版本(虚拟节点)

如果出现极限情况下,因为节点分部不均匀而造成数据倾斜问题。例如系统只有两台机器,然后大量的数据都集中某一台机器:
在这里插入图片描述

这个根本原因就是节点太少,hash算法不均衡造成的,为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希(可以用原节点key+"##xxxk"作为每个虚拟节点的key,然后求hashcode),每个计算结果位置都放置一个服务节点,称为虚拟节点。

具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,可以为每台服务器虚拟出N个虚拟节点:

  • Node A可以虚拟出Node A1,Node A2,Node A3
  • Node B可以虚拟出Node B1,Node B2,Node B3

于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:
在这里插入图片描述
数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

5. 作为虚拟节点来解决以下两种情况:

  • 一旦某个节点不可用,该节点将使得多个虚节点不可用,从而使得多个相邻的真实节点承载失效节点的压力,避免无虚拟节点时,实效节点附近的节点可能负载过高而引起系统雪崩
  • 一旦加入一个新节点,可以分配多个虚节点,从而使得新节点可以负载多个原有节点的压力,从全局看,较容易实现扩容时的负载均衡;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值