分布式缓存集群伸缩性设计的最主要目标:新加入缓存服务器后应使整个缓存服务器集群中已经缓存的数据尽可能还被访问到。
应用程序通过Memcached客户端访问Memcached服务器集群,Memcached客户端主要由一组API、Memcached服务器集群路由算法、Memcached服务器集群列表及通信模块构成。其中路由算法负责根据应用程序输入的缓存数据KEY计算得到应该将数据写入到Memcached的哪台服务器(写缓存)或者应该从哪台服务器读数据(读缓存)。
简单的路由算法可以用余数Hash:用服务器数目除以缓存数据KEY的Hash值,余数为服务器列表下标号。但是这种路由算法不利于分布式缓存集群扩容。
解决方案:一致性Hash算法。
一致性Hash算法通过一个叫做一致性Hash环的数据机构实现KEY到缓存服务器的Hash映射。具体算法过程为:先构造一个长度为0~的整数环(这个环被称作一致性Hash环),根据节点名称的Hash值(其分布范围同样为0~)将缓存服务器节点放置在这个Hash环上。然后根据需要缓存的数据的KEY值计算得到其Hash值(其分布范围也同样为0~),然后在Hash环上顺时针查找距离这个KEY的Hash值最近的缓存服务器节点,完成KEY到服务器的Hash映射查找。这个长度为的一致性Hash环通常使用二叉查找树实现。
但是,这个方法还存在一个小小的问题:新加入的节点只缓解了影响到的节点的数据量和负载压力,但对于其他没有影响到的节点则没有起到缓解作用。
解决方案:通过使用虚拟层的手段,将每台物理缓存服务器虚拟为一组虚拟缓存服务器,将虚拟缓存服务器的Hash值放置在Hash环上,KEY在环上先找到虚拟服务器节点,再得到物理服务器的信息。原理:新加入物理服务器节点时,是将一组虚拟节点加入环中,如果虚拟节点的数目足够多,这组虚拟节点将会影响同样多数目的已经在环上存在的虚拟节点,这些已经存在的虚拟节点又将对应不同的物理节点。最终的结果是:新加入一台缓存服务器,将会较为均匀地影响原来集群中已经存在的所有服务器,也就是说分摊原有缓存服务器集群中所有服务器的一小部分负载。在实践中,一般一台物理服务器虚拟150个虚拟服务节点。