http://lib.youkuaiyun.com/article/16/46895?knId=407
一致性Hash分布简介
在服务器数量不发生改变时,普通的Hash分布可以很好地运作。当服务器的数量发生改变时,问题就出来了,试想,增加一台服务器时,同一个key经过Hash之后,与服务器取模的结果跟没增加服务器之前的结果会不一样,这就导致之前保存的数据丢失。为了把丢失的数据减少到最少,可以采用一致性hash算法。
一致性hash算法分为6个步骤:
步骤1:
将一个32位整数0~2^32 -1想象成一个环,将0作为圆环的头,2^32 -1作为圆环的尾,把它连接起来。当然这只是想象。
步骤2:
通过Hash函数把key处理成整数。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
把key处理成整数后,就可以在环中找到一个位置与之对应,如下图
步骤3:
把memcached群映射到环上,使用Hash函数处理服务器所使用的IP地址。
假如有3台服务器,分别使用IP(127.0.0.1),IP(127.0.0.2),IP(127.0.0.3),使用下面的方法映射到环上。
- 1
- 2
- 3
步骤4:把数据映射 到服务器上
沿着环顺时针方向的key出发,知道遇到下一个服务器为止,把key对应的数据保存到这个服务器上。根据上面的方法,key4和key3保存到server2上,key2保存到server1上,key1保存到server3上。
步骤5:移除服务器
考虑一下,如果server2服务器崩溃了,那么受最大影响的仅是沿着server2逆时针出发直到下一个服务器之间的数据,也就是映射到server2上的那些数据。然后依照规则,将server2服务器上的数据移植下一个服务器上即可。
在上例中,需要进行变动的有key3和key4对应的数据,把这些数据重新映射到server1上即可。
步骤6:添加服务器。
再考虑一下,如果要添加一个服务器server4,用之前的方法把它映射到key3和key4之间,这时受到的影响是沿着server4逆时针出发直至遇到下一个服务器之间的数据,把这些数据重新映射到server4上即可。
在这里仅需要变动的只有key4对应的数据,将其重新映射到server4上即可。
使用PHP实现一致性Hash分布算法的代码如下:(注:个人理解所编写,并不权威)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
测试代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
运行结果如下:
注:关于哈希算法,读者可以自己编写自己的,也可以运用PHP自带函数或方法。
例如:一个比较简单的
- 1
一致性hash分布优化
上述方法的缺点如下:
- 服务器算出的mhash(),并不均匀,就会出现,数据分配不均的现象。
- 移除一个服务器后,会将此服务器的数据,全部转移至下一个服务器,并不能将其分担给其余服务器。
解决方法:
创建若干的虚拟节点,这样,done掉一台服务器的话,数据会近似均匀的分给其他几台服务器。
实现方式:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
测试:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
运行结果:
再看服务器的分布情况: