Hash一致性算法与分布式缓存服务器
在大型的分布式项目中,解决性能问题是重中之重,在前端搭建缓存服务器是常见的一种解决后台资源访问的一种方案。就以图片缓存服务器为例,用户近期访问的图片,将会被从后台读取到客户端,并缓存到前端缓存服务器中,当再次访问该资源时,就可以直接在前端缓存中读取,不必访问后台,这对后台服务器性能是一个很好的提升。
这样的缓存服务器为了实现负载均衡,通常不会单点,而会搭建一个集群。问题就来了,如何实现资源的负载均衡呢?如果等量的将每一个资源分布在每一个缓存服务器上,则每一次再访问该资源时,还是得依次遍历每一个缓存服务器,这样负载均衡的意义就不存在了。
再聪明些同学可能会想到Hash算法,根据图片的名字取一个Hash值,然后以缓存服务器的数量做除法取余,然后就可以将图片随机分布在各个服务器中,并在读取资源时,也能根据hash算法找到相应的服务器。但是这样的做法会引申出一个新的问题,如果添加新的节点,或者有节点挂了怎么办,这时,节点的变动就会影响hash算法,显然的不满足分布式CAP思想中的分区容错性(A)。
本文的主角
如上描述的问题自然会有一个解决方案--Hash一致性算法。
在最原始的Hash算法中,我们是使用服务器的数量取模,Hash一致性算法则以2^32取模,如此构建出一个圆形的Hash模型,如下:

如此的一个Hash模型坐落了2^32个点,取模后的key就会被映射到模型上。另外的,不同于简单Hash算法只是对图片对象进行取模,在Hash一致性算法中,会首先地对缓存服务器的IP地址取模,这也是为什么选择2^32这个数字的原因。
取模ip地址这只是第一步;
第二步,图片会以2^32次方取模,坐落在圆形hash模型的某一个点上,并顺时针的找到下一个IP节点,完成映射;
来看看如上操作解决了最初的哪些问题:
如果节点挂了,或者增加新的节点,只会影响单个节点的缓存,当发现挂了的节点不复存在时,就会去找到下一个节点,读取并缓存到新的节点上,不至于全部崩盘。
引申出新的问题:这样的节点均匀么?很显然一个节点到他上一个逆时针节点的弧长就是他的权重,但是由于IP地址的原因,通常节点会分布的比较集中,如此一来,其中的一个节点将会面临最大的负载(骨干的现实还是取代了丰满的理想啊)。
丰满现实
如何让Hash一致性算法变得更加的完美呢?
提出一个新的概念--虚拟节点。
虚拟节点就是真实节点对应的节点,均匀的分布在圆形Hash模型上,当图片找到指定的虚拟节点时,同样也会被映射到真实节点上,如此一来就完成了真实节点太过密集的解决方案。丰满现实Bingo!!