计算机系统应用教程网站

网站首页 > 技术文章 正文

一篇文章搞懂「一致性哈希」

btikc 2024-09-11 01:56:32 技术文章 10 ℃ 0 评论

在解决分布式系统中负载均衡的问题时候可以使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求,起到负载均衡的作用。我们常想到的就是“哈希”,另外一个名词“一致性哈希”也经常被提起,甚至再面试中也会被经常被问。

其实,一致性哈希的算法思想在日常编程中也极其重要,本文就带领大家一起学习一致性哈希。

哈希hash

首先了解一下什么是哈希,hash的意思是散列,目的将一组输入的数据均匀的分开、打散,往往用来配合路由算法做负载均衡,多用在分布式系统中。比如memcached它只提供了KV的存储、读取,如果使用了多台memcache做一个“逻辑集群”,就需要客户端做“路由算法”,来保证进去后,能“原路”拿出来。

Hash算法的最经典应用就是HashMap了,HashMap的数据结构简单如下图所示:

在HashMap中,当元素超过默认大小的时候,就涉及到一个扩容的操作,这样之前的数据分布会不会改变呢?

所以,普通Hash算法有一个明显的劣势:即当node数发生变化(增加、移除)后,数据项会被重新“打散”,导致大部分数据项不能落到原来的节点上,从而导致大量数据需要迁移。

那么就有了这样一个很重的问题:当node数发生变化时,如何保证尽量少引起迁移呢?即当增加或者删除节点时,对于大多数item,保证原来分配到的某个node,现在仍然应该分配到那个node,将数据迁移量的降到最低。

一致性Hash算法

关于一致性Hash算法,首先介绍这个算法的具体原理:

先构造一个长度为2^32的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 2^32-1])将服务器节点放置在这个Hash环上(例如下图的a\b\c\d),然后根据数据的Key值计算得到其Hash值(其分布也为[0, 2^32-1]),接着在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点,完成Key到服务器的映射查找。

这种算法解决了普通余数Hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。

当然,万事不可能十全十美,一致性Hash算法比普通的余数Hash算法更具有伸缩性,但是同时其算法实现也更为复杂。

带虚拟节点的一致性Hash算法

使用一致性Hash算法,尽管增强了系统的伸缩性,但是也有可能导致负载分布不均匀,解决办法就是使用虚拟节点代替真实节点。

比如说有Hash环上有A、B、C三个服务器节点,分别有100个请求会被路由到相应服务器上。现在在A与B之间增加了一个节点D,这导致了原来会路由到B上的部分节点被路由到了D上,这样A、C上被路由到的请求明显多于B、D上的,原来三个服务器节点上均衡的负载被打破了。某种程度上来说,这失去了负载均衡的意义,因为负载均衡的目的本身就是为了使得目标服务器均分所有的请求。

解决这个问题的办法是引入虚拟节点,其工作原理是:将一个物理节点拆分为多个虚拟节点,并且同一个物理节点的虚拟节点尽量均匀分布在Hash环上。采取这样的方式,就可以有效地解决增加或减少节点时候的负载不均衡的问题。

总结

在分布式系统中一致性hash起着不可忽略的地位,无论是分布式缓存,还是分布式Rpc框架的负载均衡策略都有所使用。欢迎大家和小强一起讨论分布式相关的知识。


?

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表