分布式系统下的哈希一致性算法设计

本文涉及:普通哈希算法存在的问题,分布式系统的哈希一致性算法,哈希一致性算法中的数据倾斜问题程序员

咱们知道,在分布式系统中当数据量没法使用单机进行存储时,最简单粗暴的方法就是水平扩展:加机器,搞集群。面试

然而全部的集群模式都会面临一个数据存放的问题:即一个集群有多台机器,咱们怎么知道此次的数据应该放在哪一个机器上呢?此次的数据放到了一台机器上我下一次读取的时候能保证还来这台机器上找么?算法

假如当前咱们有一个Redis集群,共5个节点对外提供服务bash


Hash取模
服务器

最开始的解决方案就是首先给5台机器分别编号:一、二、三、四、5
当对一个数据进行操做时首先计算key的hash而后对机器数量5进行取余,得出的余数就是须要放置的机器的编号。多线程

1复制代码
key应该放置的机器编号=hash(key) % 5复制代码

这个方案完美解决了文章开始提到的两个问题,可是你们都知道,程序员的智力是没有上限,固然主要是由于问题逼的:分布式

若是其中一台机器宕机了、或者新增了服务器,则整个集群全部的数据都须要从新计算位置,这个过程简直不要太痛苦。源码分析


一致性Hash
学习

既然出现了问题,聪明的程序员很快就想到了解决方案:一致性哈希算法
1ui

如上图所示,程序员们把全部的机器模拟成了一个虚拟的哈希环,而后设计了一个空间的大小,这个空间被平均分配到了全部机器的中间。当须要对一个key操做时,一样进行进行取模运算,只不过这里的模再也不是机器数量而是空间大小,而后根据得出的结果,去离结果顺时针最近的一个节点上操做key。

例如:当一个集群有5个节点、空间大小被设置为500的时候,当要设置一个key的hash值为601时。首先会对key的hash进行取余,601%500 结果为101,而后根据结果101顺时针查找最近的节点找到了192.168.1.3。
同理,设置另外一个key,先算hash,假如是888,则首先取余得出结果388而后得出节点192.168.1.5。

使用Hash一致性的时候若是遇到了节点宕机或者新增服务器的状况下可就简单的多了:
1

节点宕机,只须要把宕机节点的数据迁移到顺时针的下一个服务器上
1

新增节点仅仅须要迁移逆时针的第一台服务器的部分数据


数据倾斜

一致性哈希算法完美的解决了普通的哈希算法的问题,可是呢,没有十全十美的算法,一致性哈希算法一样存在一些问题。由上方的示例咱们能够看出来,当集群内扩缩容次数多了之后,数据很容易出现不均匀的状况,有的机器负责了大半的空间,而有的机器仅仅负责一点点空间。这个问题有一个名词,数据倾斜:
1

为了解决数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即将每个服务节点都计算为多个虚拟节点,避免单个节点持有连续的大空间:
1

推荐阅读

  1. SpringCloud学习系列汇总
  2. 多线程面试必备基础知识汇总
  3. Java集合源码分析汇总-JDK1.8
  4. Linux经常使用命令速查-汇总篇

博客全部文章首发于公众号《Java学习录》转载请保留 扫码关注公众号便可领取2000GJava学习资源

1

相关文章
相关标签/搜索