关于一致性哈希的一点理解

一致性哈希是分布式哈希表(DHT)其中一种实现,如读者还不是很了解分布式哈希可以看看这篇博客

在开始介绍一致性哈希概念之前,让我们来回想一下Memcache缓存的使用场景。在我们遇到的大多数业务场景中,都是读多写少,因此为了提升读取数据的性能,我们会在数据库和应用之间引入Memcache缓存。当应用规模比较小时,缓存的数据量不大,可能只需要一个Memcache实例就可以了。但是当应用规模逐渐变大之后,单个Memcache实例不能存储所有的缓存数据。 和MySQL类似,在数据量大到一定程度之后需要分库分表,我们也会对缓存数据进行类似MySQL的分库分表操作。通常会引入多个Memcache实例,根据某个字段的哈希值(例如,根据某个字段值对Memcache实例数进行取余)来决定各Memcache实例缓存的具体数据。比如,我们需要在Memcache中缓存user信息,可能会根据userId对Memcache实例个数取余来觉得某个具体的用户存储在哪个Memcache实例中。
在这里插入图片描述
如上图所示,因为有三个Memcache实例,所以是使用userId mod 3。
这种结构虽然简单,但是缺点也很明显,如果某个Memcache实例跪了,那么这个实例上的所有缓存数据都丢失了,这可能会造成大量的请求涌向数据库,造成严重的后果。而且添加或者下线实例,会造成相同的userId存储到不同的Memcache实例上。例如,在上面的例子中如果上线了一个新Memcache实例,那么原来userId后缀为4的用户信息会从原来1号实例转为0号实例。也就是说Memcache实例数的改变会导致哈希值的改变。那有没有什么办法既能解决应用需要用到多个Memcache实例,又能随意增减Memcache实例数量的办法呢?

为了解决在分布式缓存下,普通的哈希函数结果会因为缓存实例的增减而出现的哈希结果不同,无法找到原来的缓存数据的问题,科学家们提出了一致性哈希算法

  1. 首先我们把全量的缓存空间当做一个环形存储结构。环形空间总共分为2^32个缓冲区。
    在这里插入图片描述
  2. 每一个缓存key都通过哈希算法转化为一个32位的二进制数,也就对应着环形空间的某一个缓冲区。我们把所有的缓存key映射到环形空间的不同位置。
    在这里插入图片描述
  3. 我们的每一个Memcache结点也遵循同样的哈希算法,比如利用Memcache实例的IP做哈希,映射到环形空间当中。
    在这里插入图片描述
  4. 如何让key和节点对应起来呢?很简单,每一个key的顺时针方向最近结点,就是key所归属的存储结点。所以图中key1存储于node1,key2,key3存储于node2,key4存储于node3。
    在这里插入图片描述

当Memcache的结点有增加或者减少的时候,一致性哈希的优势就显现出来了。让我们来看看实现的细节:
1. 增加结点
当缓存集群的节点所增加的时候,整个环形空间的映射仍然会保持一致性哈希的顺时针规则,所以一小部分key的归属会受到影响。
在这里插入图片描述
有哪些key会受到影响呢?图中加入新结点node4,处于node1和node2之间,按照顺时针规则,从node1到node4之间的缓存不再归属于node2,而是归属于新节点node4。因此受影响的key只有key2。
在这里插入图片描述
最终把key的缓存数据从node2迁移到node4,就形成了新的符合一致性哈希规则的缓存结构。

2. 删除结点
当缓存集群的结点需要删除的时候(比如结点跪了),整个环形空间的映射同样会保持一致性哈希的顺时针规则,同样有一小部分key的归属会受到影响。
在这里插入图片描述
有哪些key会受到影响呢?图中删除了原结点node3,按照顺时针规则,原本node3所拥有的缓存数据所需要托付给node3的顺时针后继结点node1.因此受影响的key只有key4。
在这里插入图片描述
最终key4的缓存数据从node3迁移到node1,就形成了新的符合一致性哈希规则的缓存结构。

总结:

  • 所谓的一致性哈希其实就是在缓存实例数增减的情况下,大部分数据都不必迁移。相对而言,普通的哈希都是非一致性哈希。
  • 如上所示,如果在结点node1中找不到的缓存数据,会去到node2中查找,node2中查找不到会去到node3中查找,如此往复。这样的话也就是说查找效率变成了O(N),因此通常不会使用一致性哈希。这么长的查找时间有些时候简直是不能忍的,可以使用跳跃表来把查询效率优化为O(logN)。
  • 文本中使用了memcache来作为示例说明,是因为Redis集群(Redis把所有的缓存空间分为16384 slot)并没有采用一致性哈希算法,而memcache的各个客户端是现实了一致性哈希算法了的。

如果出现分布不均匀的情况怎么办?比如下图这样,按照顺时针规则,所有的key都归属于同一个结点。
在这里插入图片描述
为了优化这种结点太少而产生的不均衡情况。一致性哈希算法引入了虚拟结点的概念。所谓虚拟结点,就是基于原来的物理结点映射出N个子结点,最后把所有的子结点映射到环形空间上。
在这里插入图片描述
如上图所示,假如node1的IP是192.168.1.109,那么原node1结点在环形空间的位置就是hash(“192.168.1.109”)。
我们基于node1构建两个虚拟节点,node1-1和node1-2,虚拟节点在环形空间的位置可以利用(IP+后缀)计算,例如:
hash(“192.168.1.109#1”),hash(“192.168.1.109#2”)
此时,环形空间中不再有物理结点node1,node2,只有虚拟节点node1-1,node1-2,node2-1,node2-2。由于虚拟结点数量较多,缓存key与虚拟结点的映射关系也变的相对均衡了。

参考:
什么是一致性哈希?
聊聊一致性哈希

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值