以分布式的缓存服务器为例来分析某个key应该存储在哪个节点服务器上。
1、哈希后取模
先对key做哈希运算得到一个无符号整数,然后对n取模,n为节点服务器个数。
显然这种方式的存储,无论是增加节点还是减少节点,所有的key大部分都要重新分配,因为n发生了变化;这样的代价很大,并且作为存储设备,横向扩展或者节点宕机都是有可能的事,不适合存储。
2、一致性哈希算法 Consistent hashing
将节点服务器的名称和key都使用哈希运算得到一个32位的无符号整形,取值区间 (0, 2^32 -1],这个环的作用是,当我们部署好了服务器后,通过这个虚拟的环来决定要将key存在哪个node上,遍历node数组,找到大于等于key哈希的最小的那个节点,也就是在环上看,顺时针数,key哈希后面的最近的一个node。
这种方式比上一种方式的好处是,无论是增加还是删除node,只影响的是归属到他名下的key,所以需要重新调整分配的key要明显少很多。
当然这种方式还是有缺陷的,无论我们使用node的名称还是ip来做哈希运算,都不可避免node节点在环上分布不均的情况,比如下图:
A,B,C三个node运算后的值比较接近,根据顺时针取下规则,很显然A节点承载的区间非常大,导致A可能的压力最大。
为了优化这个情况,提出了第三种方法。
3、一致性哈希+虚拟节点
既然三个节点很可能造成很大的不均,那么三百个呢,显然能够削弱这种不均。
我们拔掉A,B,C,取而代之的在环上撒上A1-A100,B1-B100,C1-C100,这样,A1-A100之间总能有一些B和C,B1-B100之间总能有一些A和C,C1-C100之间总能有一些A和B,这种方式就比方式二相对均匀一些,我们也是顺时针原则找到key的虚拟存放点,然后再看这个点是A族还是B族还是C族,然后分配到实际存储的服务器上,