一致性hash的简单学习

参考:聊聊一致性哈希
一致性Hash
一致性Hash原理与实现
白话解析:一致性哈希算法 consistent hashing


一致性hash,为了实现什么目的?

当有多台服务器一起用来进行缓存,我们希望被均匀的缓存,如果没有任何规律的存放,访问时效率就很低,所以我们一般在分配缓存服务器的时候会进行哈希计算取模,这个时候就会出现问题,当服务器要进行扩容或者收缩就会导致所有的条目分布要进行重新计算,这对于分布式存储系统是不能接受的,因为一台机器掉线只是掉了一部分数据,但所有数据访问路由都会出问题。所有我们需要一致性hash。
为了实现扩容前后不会导致同一个key在不同的值上。一致性hash算法是对2^32想象成一个圆,称为hash环,判断一个对象应该被缓存到哪台服务器上的,将缓存服务器与被缓存对象都映射到hash环上以后,从被缓存对象的位置出发,沿顺时针方向遇到的第一个服务器,就是当前对象将要缓存于的服务器,由于被缓存对象与服务器hash后的值是固定的,所以,在服务器不变的情况下,一张图片必定会被缓存到固定的服务器上。

  • 使用机器的IP地址取模的,IPv4的地址是4组8位2进制数组成,所以用2^32可以保证每个IP地址会有唯一的映射。

当一台服务器发生故障,从这个环上移出后,缓存在这个服务器上的数据就要缓存到下一台服务器上,但是其他数据不会受到影响,只有部分缓存会失效。具有容错性和可扩展性。
数据倾斜问题?在服务节点太少的情况下,由于节点分布不均匀,可能会发生大部分数据都缓存在某一台服务器上,造成数据倾斜。解决方案:引入虚拟节点,对每一个服务器节点计算多个hash


一致性就是:扩容前后不会导致同一个 key 在不同的的值上——因此需要做数据转移来达到一致
【一致性的Hash算法是对2的32方取模。即,一致性Hash算法将整个Hash空间组织成一个虚拟的圆环,将数据Key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针查找,遇到的服务器就是其应该定位到的服务器。】


哈希一般都是将一个大数字取模然后分散到不同的桶里.
哈希表的每次扩展和收缩都会导致所有条目分布的重新计算,这个特性在某些场景下是不可接受的。
比如分布式的存储系统,每个桶就相当于一个机器,文件分布在哪台机器由哈希算法来决定,这个系统想要加一台机器时就需要停下来等所有文件重新分布一次才能对外提供服务,而当一台机器掉线的时候尽管只掉了一部分数据,但所有数据访问路由都会出问题。这样整个服务就无法平滑的扩缩容,成为了有状态的服务。

要想实现无状态化,就要用到一致性哈希了,一致性哈希中假想我们有很多个桶,先定一个小目标比如 7 个,但一开始真实还是只有两个桶,编号是 3 和 6。哈希算法还是同样的取模,只不过现在分桶分到的很可能是不存在的桶,那么就往下找找到第一个真实存在的桶放进去。这样 2 和 3 都被分到了编号为 3 的桶, 4 和 5 被分到了编号为 6 的桶。
在这里插入图片描述
这时候再添加一个新的桶,编号是 4,取模方法不变还是模 7:
在这里插入图片描述
因为 3 号桶里都是取模小于等于 3 的,4 号桶只需要从 6 号桶里拿走属于它的数字就可以了,这种情况下只需要调整一个桶的数字就可分成了重新分布。可以想象下即使有 1 亿个桶,增加减少一个桶也只会影响一个桶的数据分布

这样增加一个机器只需要和他后面的机器同步一下数据就可以开始工作了,下线一个机器需要先把他的数据同步到后面一台机器再下线
如果突然掉了一台机器也只会影响这台机器上的数据。实现中可以让每台机器同步一份自己前面机器的数据,这样即使掉线也不会影响这一部分的数据服务。

这里还有个小问题要是编号为 6 的机桶下线了,它没有后一个桶了,数据该咋办?为了解决这个问题,实现上通常把哈希空间做成环状,这样 3 就成了 6 的下一桶,数据给 3 就好了:
在这里插入图片描述



用一致性哈希还能实现部分的分布式系统无锁化,每个任务有自己的编号,由于哈希算法的确定性,分到哪个桶也是确定的就不存在争抢,也就不需要分布式锁了。

既然一致性哈希有这么多好的特性,那为啥主流的哈希都是非一致的呢?
主要一个原因在于查找效率上,普通的哈希查询一次哈希计算就可以找到对应的桶了,算法时间复杂度是 O(1),而一致性哈希需要将排好序的桶组成一个链表,然后一路找下去,k 个桶查询时间复杂度是 O(k),所以通常情况下的哈希还是用不一致的实现

当然 O(k) 的时间复杂度对于哈希来说还是不能忍的,想一下都是O(k) 这个量级了用哈希的意义在哪里?
既然是在排好序的桶里查询,很自然的想法就是二分了,能把时间复杂度降到 O(logk),然而桶的组合需要不断的增减,所以是个链表的实现,二分肯定就不行了,还好可以用跳转表进行一个快速的跳转也能实现 O(logk) 的时间复杂度。

在这里插入图片描述
在这个跳转表中,每个桶记录距离自己 1,2,4 距离的数字所存的桶,这样不管查询落在哪个节点上,对整个哈希环上任意的查询一次都可以至少跳过一半的查询空间,这样递归下去很快就可以定位到数据是存在哪个桶上。



使用场景

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

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

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

数据倾斜问题

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

为了解决数据倾斜问题,一致性Hash算法引入了虚拟节点机制,即对每一个服务器节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。
数据定位算法不变,只需要增加一步:虚拟节点到实际点的映射
所以加入虚拟节点之后,即使在服务节点很少的情况下,也能做到数据的均匀分布

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值