转自 https://www.jianshu.com/p/af7d933439a3
本文主要会围绕,redis分布式算法的原理以及环境配置搭建,和服务端客户端启动。我们会封装一个分布式Shard Redis API,最后验证一下Redis分布式环境验证。另外会解释一下,集群和分布式的概念。 (参考慕课geely课程:
来一波地址:https://coding.imooc.com/learn/list/162.html)
一、分布式算法原理
1.1传统的分布式算法.
原始的做法是对缓存项的键进行哈希,将hash后的结果对缓存服务器的数量进行取模操作,通过取模后的结果,决定缓存项将会缓存在哪一台服务器上。例如一个图片选择存哪台服务器的一个过程,
传统的分布式算法
这样Hash取模的方式是有弊端的,就是在我们业务扩展的时候,新增服务器节点,会导致一部分数据不能准确的在缓存服务器中找到。换句话说,当服务器数量发生变化的时候,所有缓存在一点时间内是失效的,当应用无法从缓存中获取数据时,则会向后端服务器请求数据,造成了缓存的雪崩,整个系统很有可能被压垮,所以,我们应该想办法不让这种糟糕的情况出现,但是由于Hash算法本身的缘故,使用取模法进行缓存时,这种情况是无法避免的,为了解决这些问题而出现一致性哈希算法诞生。
1.2Consistent hashing一致性算法原理
这和算法有一个环形hash空间的概念,通常hash算法都是将value映射在一个32位的key值当中,那么把数据首尾相接就会形成一个圆形,取值范围为0 ~ 2^32-1,这个圆环就是环形hash空间。
hash环
我们来看如何把对象映射到环形hash空间:
*只考虑4个对象Object1~Object4
*首先通过hash函数计算出这四个对象的hash值key,这些对象的hash值肯定是会落在上述中的环形hash空间范围上的,对象的hash对应的环形hash空间上的哪一个key值那么该对象就会映射到那个位置上,这样对象就映射到hash空间上
对象映射过程
然后就是把cache映射到环形hash空间,cache就是我们redis服务器,采用跟对象一样的hash算法。
redis服务器跟对象映射到hash环
可以看到,Cache和Obejct都映射到这个环形hash空间中了,那么接下来要考虑的就是如何将object映射到cache中。其实在这个环形hash空间进行一个顺时针的计算即可,例如key1顺时针遇到的第一个cache是cacheA,所以就将key1映射到cacheA中,key2顺时针遇到的第一个cache是cacheC,那么就将key2映射到cacheC中,以此类推。
object节点顺时针映射到redis节点
如果某一个cache被移除之后,那么object会继续顺时针寻找下一个cache进行映射。例如,cacheB被移除了,映射在cacheB中的object4就会顺时针往下找到cacheC,然后映射到cacheC上。
移除一个节点之后的变化
所以当移除一个cacheB时所影响的object范围就是cacheB与cacheA之间的那一段范围,这个范围是比较小的。如下图所标出的范围:
受影响的范围,相比较原始的分布式算法,影响范围小很多
而当增加一个cache节点时也是同理,例如,在acheC和cacheB之间增加了一个cacheD节点,那么object2在顺时针遇到的第一个cache就是cacheD,此时就会将obejct2映射到cacheD中。如下图:
新增redis节点
同样的,增加cache节点所影响的范围也就是cacheD和cacheB之间的那一段范围。如下图所标出的范围:
影响范围较小
1.3Hash倾斜性
上面一致性hash算法分析的都很美好,我们假设了所有的cache节点都在环形hash空间上均匀分布,但是很有可能会出现cache节点无法均匀分布在环形hash空间上。
cacheHahs之后分布到一侧
可以看到,A、B、C节点都挤在了一块,按顺时针来计算,就会有大量的数据(object)映射到A节点上,从上图中来看就会有一大半的数据都映射到A节点上,那么A节点所承载的数据压力会十分大,B、C节点则无法得到很好的利用,几乎等同闲着没事干。这就是Hash倾斜性所导致的现象,无法保证在环形hash空间上绝对的分布均匀。
1.4虚拟节点
为了解决Hash倾斜性的问题,redis引入了虚拟节点的概念,虚拟节点相当于是实际节点的一个影子或者说分身,而且虚拟节点一般都比实际节点的数量要多(可能一下多好几百倍,这个hash的环上都是密密麻麻的虚拟节点【默认的一个实际redis节点有160个虚拟节点,如果给redis实际节点配置了权重的话(默认权重是1),那虚拟节点的个数就是权重*160】)。引入虚拟节点后,object不再直接映射到实际的cache节点中,而是先映射到虚拟节点中。然后虚拟节点会再进行一个hash计算,最后才映射到实际的cache节点中。所以虚拟节点就是对我们的实际节点进行一个放大,如下图:
浅色为虚拟节点,深色为实际节点
先把对象hash到虚拟节点上,在将虚拟节点重新hash到真是的redis节点上。如下图所示:
虚拟节点hash的过程
1.5Consistent hashing命中率
命中率=(1 - n /(n+m))*100%(注释: n = 现有的节点数量;m = 新增的节点数量)