hash算法
想去了解一致性Hash算法,想必你已经了解过hash算法了,典型的Java里的HashMap里面就使用了hash算法,它的目的就是将需要存储的key均匀的分散到16位的数组内。
但是HashMap是有个扩容的概念的,而且扩容的时候需要将原有的映射关系重新映射一遍,这其实就是hash算法所表现出的不足的部分。
一致性hash算法
引入
为了弥补hash算法中当发生改变时需要全部跟着移动或者全部重新映射的硬伤,就引入了一致性Hash的概念。一致性Hash所要解决的问题就是提供这样一个想法,它能在节点的加入或者节点的减少时不会导致映射关系的重大变化。
实现思路和满足条件
1.Key通过hash算法均匀分布到一个环上。
2.节点(Server)也通过hash算法均匀分布到同个环上。
3.每个Server只负责一部分Key,这样,当Server的加入和删除,只会影响到一部分Key。
基于以上的实现思路,那么需要满足下面的几个条件:
平衡性:hash算法要均匀分布。
单调性:有新节点加入时,已经存在的映射关系不能发生变化。
分散性:避免不同的内容映射到相同的位置和相同的内容映射到不同的位置。
具体实现
1. 环型hash空间
一致性hash算法将整个哈希值空间组织成一个虚拟的32位的圆环,值为[0,2^32-1]。
2. 将Key映射到hash空间。
3. 将节点映射到hash空间。
4. 将Key映射到节点上。
顺时针方向从Key出发,遇到一个节点,就将该Key存储到这个节点上。
5.节点的变动
假设节点B(CacheB)挂了,那么此时受到影响的仅仅是沿B逆时针寻找直到遇到CacheA之间的Key,因此如果CacheB挂的话那么只要将object4重新映射到CacheC上就结束了。
假设需要添加一个节点CacheD,被添加在obejct2和object3之间,那么此时受到影响的只有object2需要重新映射。
平衡性考量
如果节点数目太少的情况下,容易造成对象不能均匀的映射到节点中。因此引入了“虚拟节点”来弥补当前节点数目不够的情况怎么去弥补平衡性。
假设当前仅有CacheA和CacheC两个节点,那么我们设置复制个数为2,也就是说为每个节点引入两个虚拟节点,CacheA1,CacheA2代表CacheA;CacheC1和CacheC2代表了CacheC。
可以借鉴的思路:
虚拟节点hash计算可以采用对应节点的IP地址加数字后缀的方式,假设:
CacheA的IP为192.168.1.122;
CacheC的IP为192.168.1.123;
CacheA1(192.168.1.122#1);CacheA2(192.168.1.122#2);
CacheC1(192.168.1.123#1);CacheC2(192.168.1.123#2);