算法 一致性hash/hash环

问题

在解决分布式系统中负载均衡的问题时候可以使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡的作用。
但是普通的余数hash(hash(比如用户id)%服务器机器数)算法伸缩性很差,当新增或者下线服务器机器时候,用户id与服务器的映射关系会大量失效。一致性hash则利用hash环对其进行了改进。

什么是一致性hash/hash环

一致性hash算法是对 2^{32} 取模,将整个hash空间组织成一个虚拟的圆环,因此hash函数的值空间为:0~ 2^{32}-1 (32位无符号整数)
整个圆环以顺时针方向组织,圆环正上方的点代表0,0点右侧的第一个点代表1,以此类推。

假设有3台服务器:服务器A,服务器B,服务器C,根据一致性hash算法计算对应的hash值:hash(服务器A),hash(服务器B),hash(服务器C),这样每台服务器就确定在了哈希环的一个位置上

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

一致性Hash算法的容错性和可扩展性

现在,假设我们的Node C宕机了,我们从图中可以看到,A、B不会受到影响,只有Object C对象被重新定位到Node A。所以我们发现,在一致性Hash算法中,如果一台服务器不可用,受影响的数据仅仅是此服务器到其环空间前一台服务器之间的数据(这里为Node C到Node B之间的数据),其他不会受到影响

另外一种情况,现在我们系统增加了一台服务器NodeX。此时对象ObjectA、ObjectB没有受到影响,只有Object C重新定位到了新的节点X上。

一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,有很好的容错性和可扩展性。

数据倾斜问题(虚拟节点)

在一致性Hash算法服务节点太少的情况下,容易因为节点分布不均匀面造成数据倾斜(被缓存的对象大部分缓存在某一台服务器上)问题

一个解决方法是多加机器,但是加机器是有成本的。为了解决数据倾斜问题,一致性Hash算法引入了虚拟节点机制,即对每一个服务器节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。
如服务器A的原始值为192.168.9.20可以虚拟成192.168.9.20#1,192.168.9.20#2,192.168.9.20#3,再分别解算出hash值,以此类推。

一致性hash的特性

  • 单调性(Monotonicity),单调性是指如果已经有一些请求通过哈希分派到了相应的服务器进行处理,又有新的服务器加入到系统中时候,应保证原有的请求可以被映射到原有的或者新的服务器中去,而不会被映射到原来的其它服务器上去。
  • 分散性(Spread):一致性hash具有很低的分散性。分布式环境中,客户端请求时候可能不知道所有服务器的存在,可能只知道其中一部分服务器,在客户端看来他看到的部分服务器会形成一个完整的hash环。如果多个客户端都把部分服务器作为一个完整hash环,那么可能会导致,同一个用户的请求被路由到不同的服务器进行处理。这种情况显然是应该避免的,因为它不能保证同一个用户的请求落到同一个服务器。所谓分散性是指上述情况发生的严重程度。好的哈希算法应尽量避免尽量降低分散性。
  • 平衡性(Balance):平衡性也就是说负载均衡,是指客户端hash后的请求应该能够分散到不同的服务器上去。一致性hash可以做到每个服务器都进行处理请求,但是不同服务器的请求数量可能相差很大,这样称为一致性hash的倾斜,虚拟节点的出现就是为了解决这个问题。

猜你喜欢

转载自www.cnblogs.com/ghx-kevin/p/12950912.html