面试官让我讲一下Redis缓存的一致性hash算法

前提:

我们应该知道,使用Redis缓存是为了提高系统性能,而且当数据量特别大的时候,单台缓存服务器也会显得比较吃力,所以我们需要用到多台缓存服务器来降低单台缓存服务器的压力。这就会出现一个问题:我们如何保证数据可以均匀的分布在这几台缓存服务器上?为了解决这个问题,就出现了普通hash算法一致性hash算法。下面会对这两种方法进行介绍。

普通hash算法

普通hash算法其实就我们平时经常说的取模算法。

普通hash算法的应用场景

假设我们有三台缓存服务器,分别设置编号为0号、1号和2号,现在我们有3万条数据需要缓存,我们当然是希望这些数据能够均匀的缓存在这3台服务器上,也就是每台缓存服务器能够缓存1万条数据,那么我们需要怎么实现呢?说到这,我相信大家已经有了一个想法:就是对缓存项的键进行hash,将hash之后的结果对3(缓存服务器数量)进行取模操作,这样就可以确定缓存项会放到哪台缓存服务器上。

算法:hash(key)% N

而当我们需要访问数据时,我们只需要再次进行上述运算,就可以知道该数据项存放在哪台缓存服务器上,然后我们在这台服务器上查找数据即可,如果在这台服务器上没有找到该数据项,则说明该数据项没有缓存在缓存服务器上,也就不用去遍历其它缓存服务器了。

普通hash算法的缺点

在我们数据库的数据量足够稳定时,我们也没有必要去改变缓存服务器的数量,使用普通hash算法也就没有什么问题,因为我们把数据不管是存入缓存服务器还是从服务器中读取出来,我们都用到了hash(key)% N这个算法,只要我们的N没有改变,也就是缓存服务器数量没有改变,那么数据在缓存服务器上的位置始终是固定的

但是如果现在数据库的数据量变得越来越大,当前缓存服务器数量已经不能满足缓存要求了,就需要增加服务器数量,比如当前数量是3台,现在需要增加1台,也就是N变成了4,如果还用hash(key)% N 这个算法的话,在我们取数据的时候,缓存在一定时间内是失效的(因为我们之前把数据存入缓存的时候,N是3,现在取这个数据的时候,N变成了4,),进而引发缓存雪崩,所有请求直接打到数据库上面,整个系统很有可能被压垮。所以为了解决这个问题,就有了一致性hash算法。

一致性hash算法

什么是一致性哈希算法

其实一致性hash算法和普通hash算法一样,都是采用取模的方法,只不过普通hash算法是对缓存服务器的数量进行取模,而一致性hash算法是对2^32取模。

普通hash算法:hash(key)% N

一致性hash算法:hash(key)% 2^32

一致性hash算法关键步骤:

1)一致性hash算法将整个哈希值空间按照顺时针方向组织成一个虚拟的圆环,俗称hash环。

我们将 2^32 想象成一个圆,像钟表一样,钟表的圆可以理解成由60个点组成的圆,而此处我们把这个圆想象成由2^32个点组成的圆,示意图如下:

圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1,我们把这个由 2^32 个点组成的圆环称为hash环。

2)接着将各个服务器的IP(或者是服务器主机名)使用hash函数(一致性hash算法)进行哈希,从而可以确定每个服务器在hash环上的位置。

哈希算法:hash(服务器的IP) % 2^32

        上述公式的计算结果一定是 0 到 2^32-1 之间的整数,那么上图中的 hash 环上必定有一个点与这个整数对应,所以我们可以使用这个整数代表服务器,也就是服务器就可以映射到这个环上,假设我们有 ABC 三台服务器,那么它们在哈希环上的示意图如下:

 

3)最后使用算法定位数据在哪台服务器上:将数据key使用相同的hash函数计算出hash值,并确定此数据在hash环上的位置,然后从该位置沿hash环顺时针寻找,找到的第一台服务器就是存放该数据项的服务器。

 

一致性hash算法的优点

在介绍普通hash算法时有说到,如果只是简单对缓存服务器数量进行取模操作,那么当服务器数量发生变化时,会产生缓存雪崩,进而有可能导致系统崩溃。

而使用一致性hash算法就可以很好的解决这个问题,因为一致性hash算法对于缓存服务器数量的增减都只需要重定位hash环空间中的一小部分数据,所以只会出现部分缓存失效,不至于将所有压力在同一时间集中到后台服务器上,具有很好的容错性和可扩展性。

 

注意:一致性hash算法是会出现部分缓存失效的场景的。如上有3台缓存服务器A、B、C顺时针分布在hash环上,那么正常情况下,在A和B之间的数据项会存放在B上,但是如果B服务器出现故障,将B移除后,原本在A和B之间的数据项会被重定位到C上,所以缓存失效的部分其实就是A到B之间的数据。

而普通hash算法是会出现绝大部分缓存失效的。因为在B移除后,缓存服务器的数量变成了2,所以从缓存中读取数据的时候,是极易出现缓存失效的(一个除法连除数都变了,那它的余数是有极大的可能会发生波动的),所以每个缓存服务器里面的几乎所有数据项都会发生迁移。

hash环的倾斜

一致性hash算法在缓存服务器节点太少的情况下,是很容易因为节点在hash环上分布不均匀而造成数据倾斜的问题,也就是绝大部分数据会被集中缓存在某一台服务器上,从而出现数据分布不均匀的情况,这就是hash环的倾斜。

比如3台缓存服务器节点,理想的情况是这3台服务器节点能够均等分这个hash环,但是实际情况极有可能不是这样,会出现3个节点在hash环上挤在一起的情况,也就是hash环的倾斜。当然这仍然有可能引起系统的崩溃。为了解决数据倾斜问题,一致性hash算法引入了虚拟节点机制。

虚拟节点机制

虚拟节点机制的引入是为了解决一致性hash算法造成的数据倾斜问题。也就是对每一个服务节点计算多个哈希,每个计算结果位置在hash环上都放置一个此服务节点,这些节点就称为虚拟节点,一个实际物理节点可以对应多个虚拟节点,虚拟节点越多,hash环上的节点就越多,缓存被均匀分配的概率就越大,hash环倾斜所带来的影响就越小,同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射。比如可以在服务器IP或主机名的后面再加编号来对应。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值