什么是 常规的 hash算法?
以分布式缓存为例,假设现在有3台缓存服务器(S0,S1,S2),要将一些 文件 尽可能平均地分配到不同的服务器上,hash算法的做法是:
(1) 以 文件 的名称作为key,然后对其做hash运算。
(2) 将hash值对服务器数量进行求余,得到服务器编号,最后存入即可。
举个demo:
1111.txt 需要存入, 我们就得到hash(csdn.jpg) = 5
-------> 5%3 = 2 得到数据存入S2
上面的算法
好像可以把文件均衡地分配到不同的服务器,当获取数据的时候也可以根据同样的思路访问对应的服务器,避免全局扫描。
但这个时候服务器进行了扩容,加入了S4,我们还能否正常获取数据呢?
假设还是根据同样的思路获取1111.txt,我们就会得到 hash(csdn.jpg)%4 = 1。
我们去S1是无法获取数据的,
这个时候就有可能会引发缓存的血崩,大量的请求落到数据库上。
一致性Hash算法对于节点的增减都只需要 重定位 环空间中的一小部分数据,具有较好的容错性和可扩展性。
一致性Hash算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性Hash算法是对2^32取模,什么意思呢?
简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形)
同样以1111.txt 为例,我们照样算出 hash(csdn.jpg)%2^32 的值,然后映射到hash环上,然后以该点出发,顺时针遇到的第一个服务器,即为数据即将存储的服务器。
虽然增加了节点D后,1111.txt 的缓存失效了,
但是,分布在 A-B,B-C 以及 D-A上面的数据仍然有效,
失效的只是C-D段的数据(原来的数据存在A节点,但是此时顺时针获取的服务器是D)。
这样就保证了缓存数据不会像hash算法那样大面积失效,同样起到减轻数据库压力的效果。
,