一致性哈希算法以及其PHP实现详细解析


Posted in PHP onAugust 24, 2013

在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:  轮循算法(Round Robin)、哈希算法(HASH)、最少连接算法(Least Connection)、响应速度算法(Response Time)、加权法(Weighted )等。其中哈希算法是最为常用的算法.

典型的应用场景是: 有N台服务器提供缓存服务,需要对服务器进行负载均衡,将请求平均分发到每台服务器上,每台机器负责1/N的服务。

常用的算法是对hash结果取余数 (hash() mod N):对机器编号从0到N-1,按照自定义的hash()算法,对每个请求的hash()值按N取模,得到余数i,然后将请求分发到编号为i的机器。但这样的算法方法存在致命问题,如果某一台机器宕机,那么应该落在该机器的请求就无法得到正确的处理,这时需要将当掉的服务器从算法从去除,此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算;如果新增一台机器,会有N /(N+1)的服务器的缓存数据需要进行重新计算。对于系统而言,这通常是不可接受的颠簸(因为这意味着大量缓存的失效或者数据需要转移)。那么,如何设计一个负载均衡策略,使得受到影响的请求尽可能的少呢?

在Memcached、Key-Value Store、Bittorrent DHT、LVS中都采用了Consistent Hashing算法,可以说Consistent Hashing 是分布式系统负载均衡的首选算法。

1、Consistent Hashing算法描述

下面以Memcached中的Consisten Hashing算法为例说明。
由于hash算法结果一般为unsigned int型,因此对于hash函数的结果应该均匀分布在[0,232-1]间,如果我们把一个圆环用232 个点来进行均匀切割,首先按照hash(key)函数算出服务器(节点)的哈希值, 并将其分布到0~232的圆上。

用同样的hash(key)函数求出需要存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器(节点)上。

一致性哈希算法以及其PHP实现详细解析 Consistent Hashing原理示意图

新增一个节点的时候,只有在圆环上新增节点逆时针方向的第一个节点的数据会受到影响。删除一个节点的时候,只有在圆环上原来删除节点顺时针方向的第一个节点的数据会受到影响,因此通过Consistent Hashing很好地解决了负载均衡中由于新增节点、删除节点引起的hash值颠簸问题。

一致性哈希算法以及其PHP实现详细解析 Consistent Hashing添加服务器示意图

虚拟节点(virtual nodes):之所以要引进虚拟节点是因为在服务器(节点)数较少的情况下(例如只有3台服务器),通过hash(key)算出节点的哈希值在圆环上并不是均匀分布的(稀疏的),仍然会出现各节点负载不均衡的问题。虚拟节点可以认为是实际节点的复制品(replicas),本质上与实际节点实际上是一样的(key并不相同)。引入虚拟节点后,通过将每个实际的服务器(节点)数按照一定的比例(例如200倍)扩大后并计算其hash(key)值以均匀分布到圆环上。在进行负载均衡时候,落到虚拟节点的哈希值实际就落到了实际的节点上。由于所有的实际节点是按照相同的比例复制成虚拟节点的,因此解决了节点数较少的情况下哈希值在圆环上均匀分布的问题。

一致性哈希算法以及其PHP实现详细解析 

虚拟节点对Consistent Hashing结果的影响

从上图可以看出,在节点数为10个的情况下,每个实际节点的虚拟节点数为实际节点的100-200倍的时候,结果还是很均衡的。

第3段中有这些文字:“但这样的算法方法存在致命问题,如果某一台机器宕机,那么应该落在该机器的请求就无法得到正确的处理,这时需要将当掉的服务器从算法从去除,此时候会有(N-1)/N的服务器的缓存数据需要重新进行计算;”

为何是 (N-1)/N 呢?解释如下:

比如有 3 台机器,hash值 1-6 在这3台上的分布就是:
host 1: 1 4
host 2: 2 5
host 3: 3 6
如果挂掉一台,只剩两台,模数取 2 ,那么分布情况就变成:
host 1: 1 3 5
host 2: 2 4 6

可以看到,还在数据位置不变的只有2个: 1,2,位置发生改变的有4个,占共6个数据的比率是 4/6 = 2/3这样的话,受影响的数据太多了,势必太多的数据需要重新从 DB 加载到 cache 中,严重影响性能

【consistent hashing 的办法】
上面提到的 hash 取模,模数取的比较小,一般是负载的数量,而 consistent hashing 的本质是将模数取的比较大,为 2的32次方减1,即一个最大的 32 位整数。然后,就可以从容的安排数据导向了,那个图还是挺直观的。
以下部分为一致性哈希算法的一种PHP实现。点击下载

PHP 相关文章推荐
使用字符串函数输出整数化的PHP版本号
Oct 09 PHP
使用 php4 加速 web 传输
Oct 09 PHP
用PHP查询搜索引擎排名位置的代码
Jan 05 PHP
PHP 循环列出目录内容的函数代码
May 26 PHP
php列出一个目录下的所有文件的代码
Oct 09 PHP
浅谈php中mysql与mysqli的区别分析
Jun 10 PHP
PHP实现的封装验证码类详解
Jun 18 PHP
php var_export与var_dump 输出的不同
Aug 09 PHP
php用户注册时常用的检验函数实例总结
Dec 22 PHP
实例详解PHP中html word 互转的方法
Jan 28 PHP
Yii控制器中filter过滤器用法分析
Jul 15 PHP
PHP常用操作类之通信数据封装类的实现
Jul 16 PHP
PHP如何利用P3P实现跨域
Aug 24 #PHP
PHP引用符&的用法详细解析
Aug 22 #PHP
新手菜鸟必读:session与cookie的区别
Aug 22 #PHP
PHP mysql与mysqli事务使用说明 分享
Aug 17 #PHP
php中url传递中文字符,特殊危险字符的解决方法
Aug 17 #PHP
测试PHP连接MYSQL成功与否的代码
Aug 16 #PHP
PHP 通过Socket收发十六进制数据的实现代码
Aug 16 #PHP
You might like
PHP flock 文件锁详细介绍
2012/12/29 PHP
ThinkPHP模版中导入CSS和JS文件的方法
2014/11/29 PHP
帝国CMS留言板回复后发送EMAIL通知客户
2015/07/06 PHP
PHP传值到不同页面的三种常见方式及php和html之间传值问题
2015/11/19 PHP
PHP函数shuffle()取数组若干个随机元素的方法分析
2016/04/02 PHP
PHP实现二维数组按照指定的字段进行排序算法示例
2019/04/23 PHP
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
提高javascript效率 一次判断,而不要次次判断
2012/03/30 Javascript
javascript计算当月剩余天数(天数计算器)示例代码
2014/01/09 Javascript
jquery.mobile 共同布局遇到的问题小结
2015/02/10 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
详解Vue.js动态绑定class
2016/12/20 Javascript
微信小程序左滑删除效果的实现代码
2017/02/20 Javascript
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
vue生成随机验证码的示例代码
2017/09/29 Javascript
JavaScript获取用户所在城市及地理位置
2018/04/21 Javascript
AngularJS中ng-options实现下拉列表的数据绑定方法
2018/08/13 Javascript
vue防止花括号{{}}闪烁v-text和v-html、v-cloak用法示例
2019/03/13 Javascript
弱类型语言javascript开发中的一些坑实例小结【变量、函数、数组、对象、作用域等】
2019/08/07 Javascript
解决Mint-ui 框架Popup和Datetime Picker组件滚动穿透的问题
2020/11/04 Javascript
JavaScript中遍历的十种方法总结
2020/12/15 Javascript
python抓取网页中图片并保存到本地
2015/12/01 Python
python做量化投资系列之比特币初始配置
2018/01/23 Python
浅谈python常用程序算法
2019/03/22 Python
Python2与Python3的区别实例总结
2019/04/17 Python
Python numpy.zero() 初始化矩阵实例
2019/11/27 Python
python numpy实现rolling滚动案例
2020/06/08 Python
澳大利亚领先的宠物用品商店:VetSupply
2017/09/08 全球购物
意大利制造的男鞋和女鞋:SCAROSSO
2018/03/07 全球购物
网络安全方面的面试题
2015/11/04 面试题
安全生产先进个人总结
2015/02/15 职场文书
2015年家长学校工作总结
2015/04/22 职场文书
新娘婚礼答谢词
2015/09/29 职场文书
2016年优秀教师先进事迹材料
2016/02/26 职场文书
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python
Python Pandas pandas.read_sql函数实例用法
2021/06/21 Python