一致性哈希算法原理

1.为什么出现一致性HASH算法

1.1 传统哈希方式:

在分布式缓存系统中吗,需要将数据均匀的分布到缓存服务器集群的不同机器上。

  • 需要对缓存的keyhash值计算,
  • hash值除以服务器节点的数量取模计算出数据需要落在哪台服务器节点上。

这种算法很简单,也可以实现数据的均匀分布。但是增加或者减少数据节点的时候会导致所有缓存数据失效。

举个栗子:
例如10条数据,3个节点,如果按照传统hash结构对3进行取模

  • node a:0,3,6,9
  • node b:1,4,7
  • node c:2,5,8

当增加一个节点的时候,数据分布变更为对4进行取模

  • node a:0,4,8
  • node b:1,5,9
  • node c:2,6
  • node d:3,7

然后,我们就可以看到,我们需要迁移的节点:3,4,5,6,7,8,9成本是不是很高。

1.2 一致性哈希方式:

一致性Hash算法最关键的区别就是:对节点和数据,都做一次哈希运算,然后比较节点和数据的哈希值,数据存放在下一个的节点中,这样就会保证节点增加或者减少的时候,影响的数据最少。

还是刚才的例子(使用简单的字符串ascii码做哈希key
1. 求出数据的hash值:

  • 0:192
  • 1:196
  • 2:200
  • 3:204
  • 4:208
  • 5:212
  • 6:216
  • 7 :220
  • 8:224
  • 9:228

2. 求出节点的hash值:

  • node a:203
  • node g:209
  • node z:228

这时候,我们就可以将整个Hash值看做一个环,比较数据和节点的hash值,如果大于228,那么就归到前面的203上。

一致性哈希算法原理_第1张图片
一致性hash算法

3. 求出节点的hash值:

  • node a:0,1,2
  • node g:3,4
  • node z:5,6,7,8,9

4. 加入了node:n节点之后

  • node n:216

5. 这个时候对应的数据就会做迁移

一致性哈希算法原理_第2张图片
迁移后的一致性hash算法
  • node a: 0,1,2
  • node g:3,4,
  • node n:5,6
  • node z:7,8,9

于是我们可以看到:只有5,6节点需要迁移。

小胖:这个算法是厉害,但是若是服务节点过少的情况下,是不是会导致节点分配不均匀可能会导致数据倾斜的问题呀?

一致性哈希算法原理_第3张图片
一致性hash算法分配不均

为了解决数据倾斜的问题,一致性哈希算法引入了虚拟节点机制:即对每一个服务节点计算多个哈希,每个计算得到的Hash位置都放置一个此服务节点,称虚拟节点。具体可以在服务器ip或主机名的后面增加编号来实现

2.一致性HASH性质:

考虑到分布式系统每个节点都有可能失效,并且新的节点都很可能动态的增加进来,如何保证当系统的节点数目发生改变时仍然对外能提供良好的服务?

尤其是在设计分布式缓存系统时,如果某台服务器失效,对于整个系统来说如果不采用合适的算法来保证一致性,那么缓存于系统中的所有数据都可能会失效(即:由于系统节点数目变少,客户端在请求某一对象时需要重新计算其hash值,由于hash值已经发生改变,所有很可能找不到保存该对象的服务器节点)

一致性hash算法应该满足一下几个方面:

* 平衡性(Balance)

平衡性是指哈希的结果能尽可能分布到所有的缓存中去,这样就可以使得所有的缓存空间都得到利用。

* 单调性(Monotonicity)

如果已经有一些内容通过hash分派到相应的缓存中,又有新的缓存区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以映射到新的缓冲区中,而不会映射到旧的缓存集合中的其他缓存区。
比如:最简单的线性哈希:x=(ax+b)mod(P)P表示全部缓存区的大小。不难看出,当缓冲大小发生变化时(从P1到P2)原先的哈希结果均会发生改变。原有的数据映射到了旧的缓存区。从而不满足单调性的要求。

__*分散性(Spread) __

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

* 负载(Load)

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

* 平滑性(Smoothness)

平滑性是指:缓存服务器的数目平滑改变和缓冲对象的平滑改变是一致的。

本文参考:
一致性哈希算法原理
一致性HASH算法

你可能感兴趣的:(一致性哈希算法原理)