一致性哈希在哈希算法基础上, 适用于动态变化的Cache环境中
如果我们有4台Cache服务器来存放一些对象, 可以用简单的办法来分配:object.hashCode() % 4
.
object.hashCode() % 4 == 0
object.hashCode() % 4 == 1
object.hashCode() % 4 == 2
object.hashCode() % 4 == 3
动态变化体现在, 如果因为某些原因Cache服务器少了一台或者多了一台, 我们怎么处理对象与服务器的关系呢?
少了一台应该%3
, 多了一台应该%5
, 这样服务器上原来存放的对象与服务器的对应关系就全乱了
一致性哈希算法采用一种新的方式来解决问题,不再仅仅依赖object.hashCode()本身,而且将Cache的配置也进行哈希运算。具体步骤如下:
假设在这个环形哈希空间中, Cache5被映射在Cache3和Cache4之间, 那么受影响的将仅是沿Cache5逆时针遍历, 直到下一个Cache(Cache3)之间的对象. 只对这些对象进行转移即可.
Cache3~Cache5之间部分原来映射到Cache4, 现在应该映射到Cache5;
Cache5~Cache4之间部分原来映射到Cache4, 现在还是映射到Cache4, 不受影响;
假设在这个环形哈希空间中, Cache3被移除, 那么受影响的将仅是沿Cache3逆时针遍历直到下一个Cache(Cache2)之间的对象
原来Cache2~Cache3之间部分原来映射到Cache3, 现在应该映射到Cache4;
原来Cache3~Cache4之间部分原来映射到Cache4, 现在还是映射到Cache4, 不受影响;
考虑到哈希算法并不是保证绝对的平衡, 尤其Cache较少的话, 对象并不能被均匀的映射到Cache上. 为了解决这种情况引入了”虚拟节点”的概念.
虚拟节点是实际节点在环形空间的复制品, 一个实际节点对应了若干个”虚拟节点”, 这个对应个数也称为”复制个数”, “虚拟节点”在哈希空间中以哈希值排列.
仍以4台Cache服务器为例,设置”复制个数”为2后, 共有8个“虚拟节点”分部在环形区域上, 会如下图一样:
引入了”虚拟节点”后,映射关系就从对象-->Cache服务器
转换成了对象-->虚拟节点-->Cache服务器
. 当然虚拟节点与真正的服务器之间也有对应关系. 查询对象所在Cache服务器的映射关系整个流程如下图所示: