今天早上逛B站的时候首页给我推荐了一个视频,关于面试中一致性哈希算法的回答,好奇心驱使我点了进去。
时长:1小时半...
很纳闷为什么这个浅显易懂的概念需要讲这么久,越来越多培训机构的营销号在发一些明明10分钟解决的问题却要将几个小时的视频,打上一些骗小白的标题,浪费几个小时看完直接会自闭。
引入问题
我们先来看一个分布式缓存的应用前景。
我们有三台缓存服务器S0,S1,S2。
现在有3万张图片需要存储到这三台服务器,最好能够均匀的缓存在服务器上。
(可能有人要问了,直接平均分配S1放第一到一万张...)
如果说我们以后还要添加缓存服务器呢?如果说以后还要添加图片呢? 直接分配无异于直接定死了规则,以后扩展就是一个坑。
简单的做法是对图片进行哈希算法取值,把图片名称当作Key。
哈希算法有很多种,这个你暂时不理解也没关系,它可以对一个Key进行计算获得一个整数。
对于同一张图片,我们进行哈希之后得到的整数永远是同一个,而不同图片哈希有可能是同一个整数(哈希冲突)。
所以现在我们可以对图片进行哈希取值,得到的值对3取模,那么每张图片都可以得到一个0到2的整数,这就对应我们服务器的编号。
流程如下:
这样我们就可以把图片随机分配了,现在我们新来的图片只需要哈希取值之后再取模就可以知道放到哪个服务器,因为图片名称是key,所以我们要找一个图片也可以通过哈希来找到存放在哪台服务器。
现在有一个问题是,如果说我们要添加一台服务器,那么取模的值3需要变成4,而且之前存储的图片都需要重新计算进行改变。因为多了一台服务器,我们在找图片的时候用了4取模来找,而在存储时用的是3取模来存储。
新加一台服务器会导致整个缓存的修改,所以这种方法不适于添加服务器。
一致性哈希算法
对于上面的问题,我们可以通过哈希环来解决,这就是一致性哈希算法的核心了。
我们创建一个环,起始位置是0,终止位置是2的32次方。
对于三台服务器,我们对它们也进行哈希求值(现在不需要取模了),通过哈希我们得到它们在环上的位置。
得到服务器的位置之后,我们可以再来对图片进行哈希取值拿到它们在环中的位置。
此时,如果我们要寻找图片0存储在哪个服务器,就可以对图片0先进行哈希取值,得到它在环上的位置,从那个位置开始顺时针遍历,找到的第一台服务器就是它的存储位置。
图片0,图片32在服务器S0。
图片9在服务器S2。
这时如果我们要新添加一台服务器S3,可以先求得它的哈希值找到在环上的位置。
假如说现在得到的时下图位置。
此时图片9的缓存服务器就会变成服务器S3,而其它图片不会有缓存失效问题。
一致性哈希算法可以很大程度上解决添加服务器之后缓存失效的问题,它会用局部失效来保证大部分缓存能够存活,对于图片9这种失效的缓存,就可以走正常的访问路线,直接请求服务器数据库获得图片了。
最后
一致性哈希算法有一个坑,在我们运气不好的情况下,可能三台服务器哈希取值会非常接近。
这种情况下我们可以对三台服务器进行虚拟化,比如说把S0虚拟为S00,S01,S02,S03...把它们分布在环上。
一致性哈希在分布式缓存中有很大作用,同样面试也是常常问到,虽然说我们平常自己学习用不到(没钱买这么多服务器),但是这种分布式算法思想还是很有用的。