文章目录
Hash取余法与Hash一致性算法
一、Hash取余法
Hash取余法其实非常简单,只要学过数据结构哈希表的大概都会知道(常用算法)
Hash取余法在分布式系统中的使用
1.1 Hash取余法是什么?
为了简单说明问题,就不说微服务、redis之类的东西了(下面这个例子并不符合当前开发的模式,但足以说明Hash取余能解决的问题以及带来的问题)
以下图为例。
下面每个tomcat都是一个单体应用,通过nginx负载均衡搭建后端应用集群。为了session能够的正确获取,通过nginx的取余算法来达到负载均衡的目的
负载均衡算法:Hash(ip地址)%tomcat总数即(“ip地址”.hashCode&Integer.MAX_VALUE)%tomcat总数
通过Hash算法,得到ip地址的hash值(得出一个整数),再通过取余计算,因为这里的tomcat为三台,所以这里的余数为3,那么这个ip地址每次访问都总是可以分配到同一台tomcat上去
优点:
1)、这种算法及其简单,并且效率较高(CPU最擅长的就是计算)
2)、IP地址的hash值总是一样的,可以解决每次请求被负载均衡到其他tomcat导致session失效的问题
缺点:
1)、当增加/减少tomcat的数量时,会导致大量的session失效。
我们可以这么算一下,一开始三台tomcat存着的session,假如因为三台tomcat承受不住过多的访问压力,需要新增一台tomcat,那么tomcat的数量就会变成4台,那么就会出现这样的问题,Hash(ip地址)%4,那么所有的请求都会被重新hash化,访问的tomcat都会变得不同,这样会导致大量的session失效。与未增加tomcat之前,命中同一台tomcat的概率为1/4=25%,那么说大概就会有75%概率的session失效。同样假如tomcat宕机tomcat减少了一台,从之前的3台变成了2台,那么就会有50%的概率导致session失效。
为了解决这种大量的session失效问题,就引入了hash一致性算法的概念
二、Hash一致性算法
2.1 什么是Hash一致性算法
Hash一致性算法是1997年由麻省理工提出的一种理论。
Hash一致性算法是这样的,我们把Hash值把它看成一个圆环即整个最大的Hash值为2^32-1(大概为43亿多),最小值为0,并且将其固定为43亿多+1=0,0-1=43亿多(这里很像C语言的unsigned int)。这样整个Hash值就是一个大圆环了。
这里我通过Hash的取余法来计算出,三台tomcat所在的位置。即 Hash(tomcat的ip)%43亿
可以得出以下的分布
当有请求时,我们就将请求的ip地址hash化,即 Hash(本次请求的IP地址)%43亿
譬如有三个请求。
分别为请求1,请求2,请求3。这时我们规定,请求将会顺时针方向寻找我们的服务器tomcat
那么请求3将会找到tomcat1,请求1将会找到tomcat2,请求2将会找到tomcat3
那么目前解决了什么问题呢?
当有9个请求,那么将会通过Hash算法,散列分配到0-43亿的位置,并且访问顺时针最近的tomcat服务器。形如下图所示。
那么当tomcat1宕机了,所有的tomcat1请求就会转向地去访问tomcat2。虽然之前tomcat1的所有请求的session都会失效,但是之前访问tomcat2和tomcat3的所有请求,仍旧访问着之前访问的服务器,所以session并不会失效。
对比之前的hash取余法,因为一台tomcat宕机或新增tomcat,导致大量的session失效。Hash一致算法会不会就好得多得多?当新增/减少足够的tomcat,Hash取余和Hash一致性两者的区别就会越来越明显了。
那么当新增tomcat,hash一致性会出现怎样的问题呢?
可以看出,新增一台tomcat4,所有部分原本访问tomcat1的请求都转向访问tomcat4了。但这些影响只是一小部分的。所以影响并不是特别大。可容错性就变强了
三、Hash一致性算法的平衡性问题
看完Hash一致性算法大家可能都会产生一个疑问。Hash一定就会散列分布嘛,总会小概率的出现一大部分的请求都分配给了tomcat1,而tomcat2和3都只分配了小部分啊。或者说太少的tomcat经过hash的散列算法分布情况不一导致部分服务器太闲,部分服务器很忙的情况出现。形如下图。tomcat2承受了大量的请求,而tomcat3和1闲的要死
为了解决这种平衡,这里引出了一种虚拟节点的概念
首先tomcat1、tomcat2、tomcat3都是真实节点
我们可以虚拟出tomcat1-1、tomcat1-2、tomcat2-1、tomcat2-2、tomcat3-1、tomcat3-2的虚拟节点
所有访问到达tomcat1-1和tomcat1-2的请求,都会转向tomcat1中去。同理2-1和2-2会访问tomcat2,到达虚拟节点的请求会转向访问其对应的真实节点。形如下图
引入虚拟节点的概念后,我们其实就可以在这里大做文章了。譬如权重的分配(tomcat1的硬件服务器性能比较好,那么分配的虚拟节点就多一些,tomcat2和3硬件服务器性能都不咋地,就分配的虚拟节点少一些)
到这里你可能还会有疑问:增加节点/删除节点那么总会有那么一部分请求会转向其他服务器啊,那么总会有那么一部分session会失效啊。这可怎么办?
其实细想一下,不知道大家有没有玩过dnf,是不是当服务器压力过大的时候就会造成部分玩家掉线?这时大家只要重新登录一下就好了(这是原来访问的服务器宕机了,那么就转向访问别的服务器),当玩家数太大,其实宕机也就导致一小部分人掉线,不会出现很大的问题。这些小问题就很难去避免了…
四、如果看完这篇文章还不太懂。推荐一下这篇文章
推荐一篇通俗易懂的Hash一致性算法参考文章
https://blog.csdn.net/bntX2jSQfEHy7/article/details/79549368