用hash做缓存,假如有三台服务器,1,2,3,有三万张图片,我想将图片平均缓存到我三台服务器上,一个服务器大概一万张,怎么去实现这个办法呢,可以用hash来取余数进行操作,加入我们是以图片的名字作为key进行hash计算,hash (图片名称)%N 其中N为我们服务器的个数,我们将hash(图片名称)这一部分进行计算后得到的是一个正数,然后除以服务器的数目进行取余数,结果将会是0,1,2三个数,对应我们的服务器的编号,当我们作为客户端去请求图片的时候,图片已经进行过hash运算了,直接找到对应服务器的编号进行图片的访问,这样解决了我需要遍历所有的服务器进行查找。
那如果我缓存的服务器的数量减少或者增加,如果还是按照原来的算法走,必定会造成缓存数据的丢失,会去向后端的服务器去请求,如果有一台缓存服务器发生了故障,那我原来缓存的位置必定会发生改变,原来本该运算后要进行缓存到某一台服务器的图片,现在找不到对应缓存服务器,肯定会发生缓存的雪崩
所以出现了一致性hash算法相当于将服务器和图片分别hash到我的hash环上进行就近缓存,hash环就是对2^32次方进行取模,从0开始一直到2^32,均匀分布在一个圆环(一个比方),0的顺时针方向的第一位为1,逆时针方向第一位为2^32,大概如下图
具体就是比方我有三个服务器A,B ,C对其进行 hash (服务器Aip)%2^32 得出来的一定是一个整数,而且一定是在0--2^32之间,那么这个数就会分布在hash环上对应的位置,相同的B,C都一样,假设我们hash过后ABC的位置如下图
然后我们将需要缓存图片的key进行hash,它的hash值也会分布在我的hash环上,
如上图,我hash到了A和C之间,图片的存储规则是顺时针方向的存储,所以应该存储到A,如果有四张的话如下图
那如果我们的hash算法将服务器和hash的图片存放位置比较相近,类似于;
所有的缓存都集中存储到了A一台,只有5到了B,那么这样A的压力就不言而喻,没有均匀可言了,辛亏hash环可以添加缓存服务器的虚拟节点,类似于虚拟机,一台实机可以虚拟多台,类似于这样:
这样的话就会尽可能的把缓存都均衡放在各个服务器
一致性hash算法的优势在哪:一个是当我有一台缓存节点挂了之后,缓存的存储不会受太大的影响,
我们将b节点拿走,本来要在B节点存储的3,因为找不到B服务器,而遵循规则缓存到C,而4的缓存节点不会发生改变,这就是一致hash的优点,如果发生服务器的增加或者减少只有部分的缓存会失效,不造成全盘皆输的可能
一致hash到此结束。