一、传统哈希算法
传统的哈希表通常使用下面的方法将key映射到数组的索引(index):
hash = hashFunc(key)
index = hash % arraySize
这种方法的不足之处是当arraySize发生改变后,所有的key都需要重新映射(remapped),因为索引的值是对arraySize求余运算获得的。
这种技术可以用于把应用程序的数据分散存储到多个数据库中,从而实现数据分区(data partition),只需要把key的哈希值跟数据库的个数进行求余运算,得到的结果就是存放这个key的数据库的序号,如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/79f6f3e8849f333e48cfc94f1cffa51c.png)
二、一致性哈希算法
1 构造值域环
一致性哈希就是用于解决传统哈希算法问题的。首先,函数
f
f
f 的输出的值范围[x0,xn]两端连起来形成环,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/2ce5e9fd977bd78a2dc28e9e64c7ce6c.png)
2 服务器节点映射
利用函数
f
f
f ,把每个节点(node,可以理解成数据库服务器,key就是服务器的ip地址)映射到环上的一个点(a point):
![](https://i-blog.csdnimg.cn/blog_migrate/6300b16b69e1ade814167b4dd76d6164.png)
环上两个节点之间形成一个分区(a partition)。如果对任何一个key使用同样的函数 f f f,最终会得到这个key在环上的一个映射点(projection):
![](https://i-blog.csdnimg.cn/blog_migrate/c3c2dcfa3cf29cb072dc82bf1003a6e6.png)
3 数据分区计算
根据上面的理论,现在的任务是要确定存放key的服务器——从key对应的环上的映射点开始,沿着环做顺时针移动,碰到的第一个服务器节点就是负责存放key的服务器。
![](https://i-blog.csdnimg.cn/blog_migrate/b8bada9e4ef09712fcdaa9f34bc6b78f.png)
注意 f ( " V e n u s " ) f("Venus") f("Venus") 映射的点位于最后一个节点之后,按照函数 f f f 环逻辑,最终找到的节点就是10.1.2.3(蓝色的节点)。
4 节点加入
节点加入并不需要所有key都重新映射。只有一部分key需要被重新映射到一个不同的节点上(粉色节点上加入,Mars数据将被映射到 10.7.5.1):
![](https://i-blog.csdnimg.cn/blog_migrate/e8cc8e5162e82750589d8ced501c4c68.png)
5 节点移除
当一个节点被从环上移除,也只会有一部分key需要被重新映射(蓝色节点移除,Venus数据被重新映射到粉色节点上):
![](https://i-blog.csdnimg.cn/blog_migrate/dfaae77d20e528f24e521ccc3a3f0fb4.png)
上面所介绍的算法就是一致性哈希的本质。这个想法是由Karger等人在1997的一篇论文 [1] 。所有节点被映射到一个环上,从而形成分区,之后再把key同样映射到环上,再沿着顺时针方向找到离key的映射点最近的节点,这个节点就是负责存储key的服务器节点。
6 数据均匀分布问题
使用一致性哈希可以避免热点问题,只要函数 f f f返回的哈希值足够均匀。所以即使多个看起来很相似的key,它们在环上的映射点也会完全不同,并且相距甚远,最终它们会被存放到不同的节点上。另外一个好处是当有新节点加入或从环上移除时,需要移动的key很容易处理,只是紧紧相邻的节点才会受到影响,对其他的节点则毫发无损。
使用一致性哈希的系统还可以使用其他技术来减轻环结构的改变所带来的不利影响,比如多节点数据副本存储。
使用一致性哈希的系统通常使用一种哈希函数的输出范围来构建环结构,哈希函数可以是SHA-1或者SHA-2。SHA-1的输出范围是从0到2160, SHA-2的输出范围各不相同,SHA-256是0到2256,SHA-512是0到2512等等。使用这些函数中的任何一个都会把节点映射到环上的一个随机位置。这样的得到的分区很可能不同的大小,换句话说就是每个节点所负责的数据量各不相同。这一特点的用处不大,不过这些哈希函数的输出范围都是固定的,所以整个环可以被预先分割为几个大小相等的分区,然后每个节点可以占有其中的几个分区,从而保证每个节点所处理的数据量基本相同。
另一个重要技术是虚拟节点(virtual nodes)。
上面的介绍的环的特点是环上的节点跟一个真实存在的物理节点进行一对一映射。这会引出一个问题,随机在环上放置节点可能会导致节点间的数据分布不均匀,如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/bcbd583448a76aa745aac1878df1d615.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9524551f0befb1494a44b83441a5ecf1.png)
有了这些虚拟节点,每个物理节点将会负责环上的多个分区。当一个节点被移除,由这个节点处理的负载会被平均分配给环上剩余的其他节点。
![](https://i-blog.csdnimg.cn/blog_migrate/a6ab37afb5cd99d1b51507156a09f593.png)
7 本质
一致性哈希解决了简单哈希算法在分布式哈希表( Distributed Hash Table,DHT) 中存在的动态伸缩等问题,目前在很多分布式系统中应用广泛,如:Amazon’s Dynamo 、Riak、Akka和 Chord等。
本文转自:一致性哈希算法,如有侵权,烦请联系删除!
引用
[1] D. Karger, E. Lehman, T. Leighton, R. Panigrahy, M. Levine, and D. Lewin, Consistent hashing and random trees: distributed caching protocols for relieving hot spots on the World Wide Web. New York, New York, USA: ACM, 1997, pp. 654–663.
[2] http://blog.carlosgaldino.com/consistent-hashing.html