一致性Hash

在解决分布式系统的负载均衡问题时,可以使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求,起到负载均衡的作用。

但问题是普通的余数Hash(Hash(用户id)%服务器数)算法扩展性很差,当新增服务器或服务器宕机时,用户id与服务器的映射关系会大量失效。一致性Hash则利用Hash环对其进行了改进。

一致性Hash简介

普通的余数Hash是映射在线性的关系中的,而一致性Hash则是新加入了Hash环。举个例子,有五台服务器A,B,C,D,对他们的ip地址进行Hash运算,hash(ipA),hash(ipB),hash(ipC),hash(ipD),计算出来的hash值是0~最大正整数直接的一个值,这四个值在一致性hash环上呈现如下图:

  • Hash环上顺时针从整数0开始,一直到最大正整数,我们根据四个ip计算的Hash值肯定会落到这个Hash环上的某一个点,至此我们把服务器的四个ip映射到了一致性Hash环

  • 当用户在客户端进行请求时候,首先根据Hash(用户id)计算路由规则(Hash值),然后看Hash值落到了Hash环的那个地方,根据Hash值在Hash环上的位置顺时针找距离最近的服务器ip.

就比如下图:
如上图可知user1,user2,user7的请求会落到服务器A进行处理,User3的请求会落到服务器B进行处理,user4,user5的请求会落到服务器C进行处理,user6的请求会落到服务器D进行处理。
如果一台服务器宕机会出现什么情况?
可以看到,服务器B宕机不会使整个系统崩溃,只有user3的映射关系被破坏。user3会被顺延到服务器C处理、
如果新加一台服务器呢?
可以对新服务器进行Hash运算,得到其在环中的位置。如下图:
 
新加了一台服务器E,根据顺时针规则可知之前user7的请求应该被服务器A处理,现在被新增的服务器E处理,其他用户的请求处理服务器不变,也就是新增的服务器顺时针最近的服务器的一部分请求会被新增的服务器所替代。

一致性hash的特性

  • 单调性(Monotonicity),单调性是指如果已经有一些请求通过哈希分派到了相应的服务器进行处理,又有新的服务器加入到系统中时候,应保证原有的请求可以被映射到原有的或者新的服务器中去,而不会被映射到原来的其它服务器上去。 这个通过上面新增服务器E可以证明,新增后,原来被A处理的user1,user2现在还是被ip1处理,原来被A处理的user7现在被新增的E处理。

  • 分散性(Spread):分布式环境中,客户端请求时候可能不知道所有服务器的存在,可能只知道其中一部分服务器,在客户端看来他看到的部分服务器会形成一个完整的hash环。如果多个客户端都把部分服务器作为一个完整hash环,那么可能会导致,同一个用户的请求被路由到不同的服务器进行处理。这种情况显然是应该避免的,因为它不能保证同一个用户的请求落到同一个服务器。所谓分散性是指上述情况发生的严重程度。好的哈希算法应尽量避免尽量降低分散性。 一致性hash具有很低的分散性

  • 平衡性(Balance):平衡性也就是说负载均衡,是指客户端hash后的请求应该能够分散到不同的服务器上去。一致性hash可以做到每个服务器都进行处理请求,但是不能保证每个服务器处理的请求的数量大致相同.因为hash(用户id)的值可能集中在某几个服务器之间。比如:

user3-user7全部映射到了服务器A上。

虚拟节点

当服务器节点比较少的时候会出现一致性hash倾斜的问题,导致不能均匀分布,一个解决方法是多加机器,但是加机器是有成本的,那么就加虚拟节点,比如上面三个机器,每个机器引入1个虚拟节点后的一致性hash环的图如下:

如此一来,user3,user4被分配到服务器A,user1,user5被分配到服务器B,user2,user6,user7被分配到服务器C,这样就实现了负载均衡。当然,生成虚拟节点的算法很重要,如果算法不够好,很可能效果并不好。

在分布式系统中一致性Hash起着不可忽略的地位,无论是分布式缓存,还是分布式Rpc框架的负载均衡策略都有所使用。

posted @ 2019-06-14 11:02  一人在山旁  阅读(328)  评论(0)    收藏  举报
Live2D