哈希算法研究

前言

    我们在高负载程序的解决方案中通常会采用软件级别的负载均衡方法。举个简单的例子比如一个站点如果是河南的访问者就让服务器A提供服务如果是上海的用户那么就让服务器B来提供服务,这样就把一个站点的负载均衡到两台服务器上了。这样做的必要性不言而喻。今天我们也不是谈这个话题,我们谈的是负载均衡的算法,如果大家对这个话题感兴趣就继续往下看。

场景

    前言中举得例子是一种情况,这种情况可以概括为“状态不重现”。意思就是上海的访问者第一次是由服务器A提供服务当第二次请求时由服务器B提供服务而逻辑上允许。这里还有另外一种情况,比如我们要建立个会话服务会话的状态数据我们分散存储到4台MySql服务器里面。在存储的时候我们用(UserID%ServerCount)来计算存储该用户会话信息的数据库,而在判断用户是否在线的时候我们还是需要这个公式来得到服务器进而判断是否该用户信息被存储。这种情况我们可以叫做状态重现型。针对这种情况我们该如何解决负载均衡的情况那?

解决方案

    毫无疑问在场景中我们用了一种方法,就是取余的方法。这种方法的好处就是分布比较均匀(前提是用户ID比较连续)。但这种方法有个问题就是存储数据后我们的服务器数量进行了添加或是减少这时如果要正确的提供服务我们就需要迁移数据了。说起来不明白我们举个例子,假设我们的用户ID是1,2,3,4,5这5个用户我们的服务器是5的时候你们提供服务器的ID是1,2,3,4,0但当我们的服务器数是4的时候(拿掉5)ID是1,2,3,0,1这时候我们看出来以往的全乱了即当为5台服务器的时候第0,1,2,3,4台服务器分别存储用户ID为5,4,3,2,1的用户信息而当服务器为4是则变为服务器ID为0,1,2,3的用户分别存储4,【5,1】,2,3如果我们要迁移数据的时候工作量太大,看来这种取余的哈希算法针对有状态的访问负载不能起到均衡的效果。那么针对这种情况有没有更好的办法那?有,各位继续往下看。

改进的解决方案

    我们来考虑这样一个问题,假设把所有的整数集合均匀的放到一个圆上然后那我们按照服务器的数量把这个圆N等份。再假设我们的用户ID是所有的整数集合,在这两种假设下我们再看看服务器从5台变成4台时数据的迁移情况,如下图

这个就是我们所说的一致性哈希算法。

针对一致性哈希有两个比较重要的点需要我们注意

1:就是我们的用户ID如何才能均匀也就是需要一种有效的哈希算法。

2:就是当我们的服务器台数发生变化的时候如何才能更多的减少数据迁移,当前的方法是配置+虚节点

结论

    一致性哈希其实重点还是如何把我们的Key转换成均匀的int值。这个那位大侠知道朢不吝赐教、

有关一致性哈希算法以及虚拟节点的信息敬请关注

1:http://www.cnblogs.com/overred/archive/2009/12/29/Consistent_Hashing.html

原文地址:https://www.cnblogs.com/tommyli/p/1646685.html