一致性HASH(哈希)算法

哈希算法

在了解一致性哈希算法之前,让我们先了解一下哈希算法

在现在大规模集群应用中,缓存是必不可少的一个标准开发配置。当缓存应用越来越多,越多越大,会应运而生分布式缓存系统。
那我们的缓存数据(k-v)如何均匀的分散到集群中呢?
相关的算法有很多,如:轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least Connection)、响应速度算法(Response Time)、加权法(Weighted )等。其中哈希算法是最为常用的算法。
最典型的场景如下:
有N台服务器提供缓存服务,需要对服务器进行负载均衡,将请求平均分发到每台服务器上,每台机器负责1/N的服务。
在这里插入图片描述
常用的算法是对hash结果取余数 (hash() mod N ):对机器编号从0到N-1,按照自定义的 hash()算法,对每个请求的hash()值按N取模,得到余数i,然后将请求分发到编号为i的机器。
但是这种做法,有个很致命的问题。如果某一台机器宕机,那么应该落在该机器的请求就无法得到正确的处理,这时需要将当掉的服务器从算法从去除,此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算;如果新增一台机器,会有N /(N+1)的服务器的缓存数据需要进行重新计算。如下面两张图所示:
在这里插入图片描述
在这里插入图片描述
对于系统而言,这通常是不可接受的(因为这意味着大量缓存的失效或者数据需要转移),因为它没有考虑容错性和扩展性。
所谓容错性是指当系统中某一个或几个服务器变得不可用时,整个系统是否可以正确高效运行;而扩展性是指当加入新的服务器后,整个系统是否可以正确高效运行

那么,如何设计一个负载均衡策略,使得发生以上情况时,将我们受到影响尽可能的减少呢?
这就引入了我们要重点讲述的一致性哈希算法

一致性哈希算法

那什么是一致性哈希算法?
一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法,常用于负载均衡。
简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0 - (2^32)-1(即哈希值是一个32位无符号整形),整个哈希空间环如下:
在这里插入图片描述
整个空间按顺时针方向组织。0和(2^32)-1在零点中方向重合。

服务器如何部署

那一致性哈希算法在使用过程中,具体是如何操作的呢?
在我们思考如何将缓存值(k-v)通过一致性哈希算法存在缓存服务器上之前,首先需要确定缓存服务器在哈希环上的位置。

具体操作如下:
将各个服务器使用H进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将三台服务器使用ip地址哈希后在环空间的位置如下:
在这里插入图片描述
那么接下来,如何定位我们的数据存储位置呢?

数据如何存储

将数据key使用相同的函数H计算出哈希值h,通根据h确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器
例如我们有A、B、C、D四个数据对象,经过哈希计算后,在环空间上的位置如下:
在这里插入图片描述
根据一致性哈希算法,数据A会被定位到服务器3上,D被定位到服务器2上,而B、C分别被定位到服务器1上。

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

既然说到了我们的哈希算法对容错性和可扩展性的处理能力有限,那么一致性哈希算法的表现如何呢?
现在假设服务器3宕机了,如下所示:
在这里插入图片描述
可以看到数据B、C、D不会受到影响,只有A数据被重定位到服务器1。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据(A数据),其它不会受到影响。

下面,我们来看另外一种情况,假设,我们在系统中新增了一台服务器4,如下所示:
在这里插入图片描述
此时数据A、C、D不受影响,只有数据B需要重定位到新的服务器4。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据(B数据),其它不会受到影响。

那么,我们的一致性哈希算法除了较好的解决了我们的容错性和可扩展性,它还有什么优点呢?

通过虚拟节点解决数据倾斜问题

不知道大家有没有发现一个问题,如果使用一致性哈希算法,在服务节点太少时,因为节点分部不均匀很容易而造成数据倾斜问题。假如我们的系统中现在只有两台服务器,其环分布如下:
在这里插入图片描述
此时数据的存储,必然会造成大量数据集中到服务器1上,而只有极少量会定位到服务器2上。

那为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制。即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。
具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,我们决定为每台服务器计算三个虚拟节点,于是可以分别计算“服务器1#1”、“服务器1#2”、“服务器1#3”、“服务器2#1”、“服务器2#2”、“服务器2#3”的哈希值,于是形成六个虚拟节点,具体如下:
在这里插入图片描述
这样就能够有效的解决我们因为服务节点过少而造成的数据倾斜问题。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值