一、普通hash算法

普通hash算法最大的特点是散列,说白了就是将一些具有相同特征的数据打散成完全不同,随机,均匀分配的数据

看这个例子

将abc和abcd进行md5运算,得到如下结果

md5
可以看出,两个及其相似的字符串进行md5后生成了两个完全不同的字符串,负载均衡正是利用这一特性,对于大量随机的请求或调用,通过一定形式的Hash将他们均匀的散列,从而实现压力的平均化。(当然,并不是只要使用了Hash就一定能够获得均匀的散列,后面会分析这一点

我们设计一个非常简单的hash算法 group = key % N,总共有3台缓存服务器,把6张图片通过这个hash算法放到对应的缓存服务器上,来实现请求的一个负载均衡

简单hash

我们不难发现,当新增一台缓存服务器后,由于N的数量增加,图片的key不变,所以接下来通过hash算法请求图片时,图片的映射会全部失效,也就是说之前的缓存会全部失效,从而导致大量请求绕过缓存去查DB,而出现缓存雪崩,DB很可能会被打挂

二、一致性Hash算法

一致性Hash算法通过环状结构(2 ^ 32)代替线性结构的方法在一定程度上解决的这个问题

一致性hash算法

假设我们现在有3台缓存服务器,用缓存服务器的hash key % 2^32生成一个结果存放在环上某一个位置,然后用同样的方法找到图片对应环上的位置,然后在图片所在环的位置顺时针查找,找到的第一台服务器就是该图片的缓存服务器,下面我们来分析一下删除和增加节点对负载均衡产生的影响。

删除0号缓存

可以发现,当0号缓存服务器被删除后,其他图片在环上的映射不会发生变化,只是原来0号缓存上的数据顺时针转移到下一个缓存服务器上,增加也如此,最终只是少部分的缓存无法命中,随着我们环上服务器数量改变,整体请求的压力也不均衡了,从而会导致数据倾斜和缓存雪崩问题,下面来分析

数据倾斜问题

之前介绍过我们的环的大小非常大(2^32),当我们的缓存服务器过少,通过一致性hash算法后导致缓存服务器挤在很小的一个区域,如下图

数据倾斜

从而会导致数据通过一致性hash算法后,大概率大量的数据会被映射在环的左侧空闲区域,最终对分布式缓存造成的影响就是,集群的每个实例上储存的缓存数据量不一致,会发生严重的数据倾斜

缓存雪崩问题

假设一种情况,现在环上的某一个节点消息,它原本负载的所有数据会顺时针转移到下一个节点,这就意味着下一个节点的压力突然变大,如果这个节点承载不住崩掉了,那么所有的负载就会顺时针转移,最终服务压力就像滚雪球一样越滚越大,从而导致服务雪崩

解决办法:引入虚拟节点

为了解决上面两种问题导致的负载均衡失衡问题,最好的办法就是增加我们节点的数量,所以我们可以增加每个节点的虚拟节点来使我们缓存服务器更可能多,这里的虚拟节点的实现我的想法是可以通过类似这种运算hash(1001#1),hash(1001#2),hash(1001#3)来实现,从而在很大程度上能大概率平衡压力,从而更好的实现负载均衡,如图

虚拟节点

一致性Hash算法能够在节点变动的情况下,导致较小数缓存命中失效

最后修改:2021 年 07 月 14 日 10 : 19 PM
如果觉得我的文章对你有用,请随意赞赏