什么是一致性Hash算法?

本文公众号来源:crossoverJie  作者:crossoverJie


当时我就是看这篇文章学习什么是一致性Hash算法的,觉得写得非常不错,分享一下2_04.png

640?wx_fmt=jpeg

当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题:

如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少。

Hash 取模

随机放置就不说了,会带来很多问题。通常最容易想到的方案就是 hash取模了。

可以将传入的 Key 按照 index=hash(key)%N 这样来计算出需要存放的节点。其中 hash 函数是一个将字符串转换为正整数的哈希映射方法,N 就是节点的数量。

这样可以满足数据的均匀分配,但是这个算法的容错性和扩展性都较差。

比如增加或删除了一个节点时,所有的 Key 都需要重新计算,显然这样成本较高,为此需要一个算法满足分布均匀同时也要有良好的容错性和拓展性。

一致 Hash 算法

一致 Hash 算法是将所有的哈希值构成了一个环,其范围在 0~2^32-1。如下图:

640?wx_fmt=jpeg

之后将各个节点散列到这个环上,可以用节点的 IP、hostname 这样的唯一性字段作为 Key 进行 hash(key),散列之后如下:

640?wx_fmt=jpeg

之后需要将数据定位到对应的节点上,使用同样的 hash函数 将 Key 也映射到这个环上。

640?wx_fmt=jpeg

这样按照顺时针方向就可以把 k1 定位到 N1节点,k2 定位到 N3节点,k3 定位到 N2节点

容错性

这时假设 N1 宕机了:

640?wx_fmt=jpeg

依然根据顺时针方向,k2 和 k3 保持不变,只有 k1 被重新映射到了 N3。这样就很好的保证了容错性,当一个节点宕机时只会影响到少少部分的数据

拓展性

当新增一个节点时:

640?wx_fmt=jpeg

在 N2 和 N3 之间新增了一个节点 N4 ,这时会发现受印象的数据只有 k3,其余数据也是保持不变,所以这样也很好的保证了拓展性。

虚拟节点

到目前为止该算法依然也有点问题:

当节点较少时会出现数据分布不均匀的情况:

640?wx_fmt=jpeg

这样会导致大部分数据都在 N1 节点,只有少量的数据在 N2 节点。

为了解决这个问题,一致哈希算法引入了虚拟节点。将每一个节点都进行多次 hash,生成多个节点放置在环上称为虚拟节点:

640?wx_fmt=jpeg

计算时可以在 IP 后加上编号来生成哈希值。

这样只需要在原有的基础上多一步由虚拟节点映射到实际节点的步骤即可让少量节点也能满足均匀性。

更多资料

这篇写得比较简洁,如果觉得还没看够的同学可以看看下面这篇:

  • https://zhuanlan.zhihu.com/p/34985026

本文的作者还写了一篇Hash算法的实际应用,有兴趣的同学也可以前往学习学习:

最后

乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!

640?wx_fmt=jpeg

有帮助?在看!转发到朋友圈! 640
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值