# 一致性Hash算法

## 一、一致性hash算法简介

在分布式集群中，对机器的添加删除，或者机器故障后自动脱离集群这些操作是分布式集群管理最基本的功能。如果采用常用的hash(object)%N算法，那么在有机器添加或者删除后，很多原有的数据就无法找到了。一致性哈希算法就是为了解决这个问题的。

一致性哈希算法是将key哈希到一个具有2^32个桶的空间环中，也是使用取模的方式，传统的取模是对服务器个数取模，一致性哈希是对2^32取模，让key固定的落在这个环中。然后将服务器也hash到这个环中，最后将key沿着顺指针方向“走”，第一台遇到的服务器就是其应该定位到的服务器。如图：

![](https://3037548586-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnpynfpU0w3FBTJVlOK%2Fsync%2Fdcbd3ef09e0a57028c0dba4694d0e64d6b42211d.jpg?generation=1591097962056747\&alt=media)

这样当机器删除或者添加时，只会影响一小部分数据，其他数据不会受到影响。比如C节点删掉了，那么对象c就会访问到节点D，可以看到只有对象c收到了影响。一般情况下，一个节点删掉后受影响的只是当前节点到上一个节点的数据。

## 二、一致性hash算法的平衡性

一致性Hash算法在服务节点太少时，容易因为节点分部不均匀而造成数据倾斜（被缓存的对象大部分集中缓存在某一台服务器上）问题，例如系统中只有两台服务器，其环分布如下：

![](https://3037548586-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnpynfpU0w3FBTJVlOK%2Fsync%2F3371920ae39d54bad37d17a4114e608f16e674be.jpg?generation=1591097961975263\&alt=media)

此时必然造成大量数据集中到Node A上，而只有极少量会定位到Node B上。为了解决这种数据倾斜问题，一致性Hash算法引入了虚拟节点机制，即对每一个服务节点计算多个哈希，每个计算结果位置都放置一个此服务节点，称为虚拟节点。具体做法可以在服务器IP或主机名的后面增加编号来实现。

例如上面的情况，可以为每台服务器计算三个虚拟节点，于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值，于是形成六个虚拟节点：

![](https://3037548586-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnpynfpU0w3FBTJVlOK%2Fsync%2F5605fe805c8601d78417ade143686547ba5d0eba.jpg?generation=1591097962107103\&alt=media)

同时数据定位算法不变，只是多了一步虚拟节点到实际节点的映射，例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中，通常将虚拟节点数设置为32甚至更大，因此即使很少的服务节点也能做到相对均匀的数据分布。

> 参考：
>
> 一致性hash算法是什么：<https://zhuanlan.zhihu.com/p/34985026>
>
> 五分钟理解一致性hash算法：<https://blog.csdn.net/cywosp/article/details/23397179>
