Consistent Hashing是一种hash算法,简单的说,在移除/添加一个cache时,它能够尽可能小的改变已存在key映射关系,尽可能的满足单调性的要求。
1、环形空间
考虑通常的hash算法都是将value映射到一个32维的key值,也即是0~2^32-1次方的数值空间;我们可以将这个空间想象成一个首(0)尾(2^32-1)相接的圆环。
2、把对象映射到hash空间
接下来考虑4个对象object1~object4,通过hash函数计算出的hash值key在环上的分布如图:
hash(object1) = key1
hash(object2) = key2
hash(object3) = key3
hash(object4) = key4
3、把cache映射到hash空间
Consistent Hashing的基本思想就是将对象和cache都映射到同一个hash数值空间中,并且使用相同的hash算法。
假设当前有A、B和C共3台cache,那么其映射结果如图:
hash(cache A) = key A
hash(cache B) = key B
hash(cache C) = key C
说到这里,顺便提一下cache的hash计算,一般的方法可以使用cache机器的IP地址或者机器名作为hash输入
4、把对象映射到cache
在这个环行空间中,如果沿着顺时针方向从对象的key值出发,直到遇见一个cache,那么就将该对象存储在这个cache上,因为对象和cache大hash值是固定的,因此这个cache必然是唯一和确定的。这样不就找到了对象和cache大映射方法了吗?!
根据上面的方法,如上图所示:object1存储在cacheA上,object2和object3存储在cacheC上,object4存储在cacheB上。
5、考察cache的变动
前面讲过,通过hash然后求余的方法带来的最大问题就在于不能满足单调性,当cache有所变动时,cache会失效,进而对后台服务器造成巨大的冲击。现在就来分析Consistent Hashing算法
- 移除cache
考虑假设cacheB挂掉了,根据上面讲到的映射方法,这时受影响的将仅是那些沿着cacheB逆时针遍历直到下一个cache(cacheC)之间的对象,也即是本来映射到cacheB上的那些对象。因此这里仅需要变动对象object4,将其重新映射到cacheC上即可
- 添加cache
再考虑添加一台新的cacheD的情况.假设在这个环行空间中,cacheD被映射到在对象object2和object3之间,这时受影响的将仅仅是那些沿objectD逆时针遍历直到下一个cache(cacheB)之间的对象(它们是也本来映射到cacheC上对象的一部分),将这些对象重新映射到cacheD上即可。因此这里仅需变动对象object2,将其重新映射到cacheD上
考量hash算法的另一个重要指标是平衡性(Balance)
平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。
hash算法并不是保证绝对的平衡,如果cache较少的话,对象并不能被均匀的映射到cache上。比如图3.17