一致性哈希算法以及其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中的array数组类型分析说明
Jul 27 PHP
PHP中call_user_func_array()函数的用法演示
Feb 05 PHP
Zend Studio去除编辑器的语法警告设置方法
Oct 24 PHP
php使用百度翻译api示例分享
Jan 31 PHP
通过PHP自带的服务器来查看正则匹配结果的方法
Dec 24 PHP
php中preg_replace正则替换用法分析【一次替换多个值】
Jan 17 PHP
PHP实现APP微信支付的实例讲解
Feb 10 PHP
PHP实现数据库的增删查改功能及完整代码
Apr 18 PHP
php获取手机端的号码以及ip地址实例代码
Sep 12 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
Feb 12 PHP
php中加密解密DES类的简单使用方法示例
Mar 26 PHP
基于PHP+mysql实现新闻发布系统的开发
Aug 06 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
人族 Terran 魔法与科技
2020/03/14 星际争霸
推荐十款免费 WordPress 插件
2015/03/24 PHP
如何使用GDB调试PHP程序
2015/12/08 PHP
javascript 检测浏览器类型和版本的代码
2009/09/15 Javascript
jquer之ajaxQueue简单实现代码
2011/09/15 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
2014/12/08 Javascript
jQuery基于图层模仿五星星评价功能的方法
2015/05/07 Javascript
jQuery实现大转盘抽奖活动仿QQ音乐代码分享
2015/08/21 Javascript
AngularJS实现单独作用域内的数据操作
2016/09/05 Javascript
基于jQuery实现中英文切换导航条效果
2016/09/18 Javascript
canvas 实现中国象棋
2017/02/17 Javascript
彻底搞懂JavaScript中的apply和call方法(必看)
2017/09/18 Javascript
微信小程序获取音频时长与实时获取播放进度问题
2018/08/28 Javascript
Vue3配置axios跨域实现过程解析
2020/11/25 Vue.js
跟老齐学Python之有容乃大的list(1)
2014/09/14 Python
30分钟搭建Python的Flask框架并在上面编写第一个应用
2015/03/30 Python
使用Python的Zato发送AMQP消息的教程
2015/04/16 Python
python和ruby,我选谁?
2017/09/13 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
2019/09/02 Python
python实现udp聊天窗口
2020/03/31 Python
python3实现语音转文字(语音识别)和文字转语音(语音合成)
2020/10/14 Python
Peter Millar官网:美国高档生活服饰品牌
2018/07/02 全球购物
Nip + Fab官网:英国美容品牌
2019/08/26 全球购物
英国最受信任的在线眼镜商之一:Fashion Eyewear
2019/10/31 全球购物
Monica Vinader官网:英国轻奢珠宝品牌
2020/02/05 全球购物
Cocopanda波兰:购买化妆品、护肤品、护发和香水
2020/05/25 全球购物
库存图片、照片、矢量图、视频和音乐:Shutterstock
2021/02/12 全球购物
《再见了,亲人》教学反思
2014/02/26 职场文书
建议书怎么写
2014/03/12 职场文书
《金孔雀轻轻跳》教学反思
2014/04/20 职场文书
个人收入证明范本
2014/09/18 职场文书
2014年十一国庆节爱国演讲稿
2014/09/23 职场文书
2014年酒店服务员工作总结
2014/12/08 职场文书
初中政治教师教学反思
2016/02/23 职场文书
Python Numpy库的超详细教程
2022/04/06 Python
python热力图实现的完整实例
2022/06/25 Python