如果有n个缓存服务器,常见的负载均衡方法是使用如下哈希方法
服务器序号= hash(key) % N (N 代表服务器池的大小)这个方法在服务器池大小固定不变时效果很好,并且数据的分布是均匀的,但 当添加服务器或现有服务器被移除时问题就产生了。
N 变了,大部分的键都被重新分配了。一致性哈希是缓解这个问题的有效技术。
定义,一致性哈希是一种特殊的哈希,如果一个哈希表被调整了大小,那么使用一致性哈希,则平均只需要重新映射
k/n 个键,k 是键的数量,n 是槽的数量。
大多数传统的哈希表中,只要槽的数量有变化,几乎所有的键都需要重新映射一遍。
假设我们使用 SHA-1 作为哈希函数f, 哈希函数的输出值范围是 :
xO, x 1, x2, x3, …, xn。
在密码学里,SHA-1 的哈希空间是 0 到 2^160 - 1,这意味着
x0 对应 0,xn 对应 2^160 - 1。
连接 x0 和 xn 两端,得到哈希环。
使用同样的哈希函数f,根据服务器的IP或者名字将其映射到哈希环上
这里使用哈希函数 没有求余运算,4个键 key0、key1、key2、key3 被映射到哈希环上。
为了确定某个键存储在哪个服务器上,从这个键在环上的位置开始顺时针查找,直到找到一个服务器为止。
按照上面描述的逻辑,如果在哈希环中添加一个新的服务器,只有少部分键需要被重新 映射到新的服务器,大部分键的位置保持不变。
当一个服务器被移除时,如果使用一致性哈希,就只有一小部分键需要重新分配位置。
一致性哈希算法是MIT的 David Karger 等人首先提出的,基本步骤如下:
两个问题:
一,考虑到可以添加或移除服务器,所以很难保证哈希环上所有服务器的分区大小相同。分区是相邻服务器之间的哈希空间。在哈希环上分配给每个服务器的分区可能很小,也可能很大
二,有可能键在哈希环上是非均匀分布的
虚拟节点是实际节点在哈希环上的逻辑划分或映射,每个服务器都可以用多个虚拟节点来表示。
为了找到某个键存储在哪个服务器上,从这个键所在的位置开始,顺时针找到第一个虚拟节点。
当虚拟节点的数量增加时,键的分布就会变得更均匀,这是因为有更多虚拟节点之后,标准差会变小, 从而导致数据分布更均匀。标准差衡量的是数据的分散程度。
当添加或移除服务器时,有一部分键需要重新分配位置,如何找到受影响的键的范围并重新为它们分配位置呢?
从新添加的节点开始,沿着哈希环逆时针移动,直到遇到另一个服务器为止,就是受影响的键的范围。
从被移除的节点开始,沿着哈希环逆时针移动,知道遇到另一个服务器为止,就是受影响的键的范围。