一致性hash算法
1.前景(hash算法)
分布式缓存:
需求:
将图片均匀的分布到3台服务器上。
方案:
使用hash算法。
对于一个key,由客户端来决定存放到哪台机器,那最简单的hash公式就是 hash(key)% N,其中N是机器的总数。
使用原理:对于同一个图片,做hash计算,由图片的名称充当key,所以得到的值是不变的,所以可以通过hash值找到图片存储的具体位置。
缺陷:
一旦机器数变少,或者增加机器,N(机器数量)发生变化,那之前存放的数据就全部无效了。
因为你按照新的N值取模计算出的机器编号,和当时按旧的N值取模算出的机器编号肯定是不等的,也就意味着缓存会失效。
缓存失效引发的问题:缓存服务器就不能起到分压的作用,那么后端服务器就会被压垮。这也就是缓存雪崩。
缓存雪崩可以设置缓存不同的过期时间来解决,但在此处,需要使用另一种数据结构了。
这个问题的解决办法就是用1种特别的Hash函数,尽可能使得,增加机器/减少机器时,缓存失效的数目降到最低,这就是Hash环,或者叫一致性Hash。
2.一致性hash算法
Hash环
上面说的Hash函数,只经过了1次hash,即把key hash到对应的机器编号。
Hash环有2次Hash:
(1)把所有机器编号hash到这个环上
(2)把key也hash到这个环上。然后在这个环上进行匹配,看这个key和哪台机器匹配。
具体来讲,如下:
假定有这样一个Hash函数,其值空间为(0到2的32次方-1) ,也就是说,其hash值是个32位无整型数字 ,这些数字组成一个环。
然后,先对机器进行hash(比如根据机器的ip),算出每台机器在这个环上的位置; 再对key进行hash,算出该key在环上的位置,然后从这个位置往前走,遇到的第一台机器就是该key对应的机器,就把该(key, value) 存储到该机器上。
首先计算出每台Cache服务器在环上的位置(图中的大圆圈);然后每来一个(key, value),计算出在环上的位置(图中的小圆圈),然后顺时针走,遇到的第1个机器,就是其要存储的机器。
这里的关键点是:当你增加/减少机器时,其他机器在环上的位置并不会发生改变。这样只有增加的那台机器、或者减少的那台机器附近的数据会失效,其他机器上的数据都还是有效的。
存在问题:hash倾斜
原因:
当你机器不多的时候,很可能出现几台机器在环上面贴的很近,不是在环上均匀分布。这将会导致大部分数据,都会集中在某1台机器上。
解决:
引入虚拟节点概念。
例:假设用机器的ip来hash,我可以在ip后面加上几个编号, ip_1, ip_2, ip_3, … 把1台物理机器生个多个虚拟机器的编号。
ip来hash,我可以在ip后面加上几个编号, ip_1, ip_2, ip_3, … 把1台物理机器生个多个虚拟机器的编号。
工作原理:数据首先映射到“虚拟机器上”,再从“虚拟机器”映射到物理机器上。因为虚拟机器可以很多,在环上面均匀分布,从而保证数据均匀分布到物理机器上面。