在设计方案数据仓库的系统架构时,为了更好地增强程序的负荷工作能力,必须将不一样的样本分布到不一样的服务项目连接点。因而,必须一种派发体制,它事实上是一种完成这一作用的优化算法。大家在这儿应用一致hash算法。

在宣布详细介绍一致hash算法以前,大家先看来一个简洁的hash算法,即取余数挑选连接点。操作步骤如下所示:

1.依据群集服务项目中的进程总数建立哈希表;2.依据键名测算键名的整数金额哈希值,用哈希值取连接点数的被除数。3.最终,依据被除数,取下哈希表中的连接点。

假定一个群集中有n个服务器节点,这种连接点序号为0,1,2,…,n-1。随后,一段数据信息(密匙,值)储存在网络服务器中。这时候,大家要如何选择服务器节点呢?依照里面的流程,大家必须测算key的哈希值,随后取n(连接点数)的被除数。最后的值是大家需要的连接点。用公式计算表明:num = hash (key)% n. Hash()是测算哈希值的涵数。这儿对hash()涵数有一定的规定。假如提升大家采用的hash()涵数,测算出的num会均匀的分散在0,1,2,…,n-1中间,那样就可以应用尽量多的服务器节点。并不是全部信息都集中化在一个或好多个服务器节点上。hash()的完成并不是此章的关键。

这类简易的求余数的方式尽管简易,但假如运用到具体的生产系统中,便会造成较大的难题。假定自己有23个服务项目连接点。依据上述方式,密匙投射到每一个连接点的几率是1/23。假如加上了服务项目连接点,此前的hach(键)% n将变为hach(键)% (n 1)。换句话说,有23/24的几率将密匙分配给新连接点。反过来,仅有1/24的几率会分派给初始连接点。一样,当您降低一个连接点时,它被分配到新连接点的几率是22/23。

由于这类状况,就必须有一种方法来预防或是降低在纵向扩大的情况下准确率减少的具体情况的产生。这类方式便是大家已经详细介绍的Consistent Hashing优化算法,大家称其为一致性hash优化算法。为了更好地掌握Consistent Hashing优化算法是怎样工作中的,大家假定企业区段 [ 0 , 1 ) 依顺时针方向的方位匀称的分散在圆上。php编码规范-php网页编程教程-第1张图片对于这样的状况,必须有方法防止或降低水准拓展时准确率的降低。这类方式便是大家已经详细介绍的一致性哈希优化算法,大家称作一致性哈希优化算法。为了更好地了解一致hash算法是怎样工作中的,大家假定企业间距[0,1]沿顺时针分布均匀在圆上。

一致性哈希优化算法原始

如果有n个服务项目连接点,每一个服务项目连接点的总数为0,1,2,…,n-1。随后大家必须一个hash()涵数来测算服务项目连接点的哈希值。假如hash()函数返回值的取值范围为[0,R],则应用公式计算v = hash(n)/R。那样获得的v将遍布在企业区段[0,1]内。因而,那样,大家的服务项目连接点就可以遍布在圆形上。

自然,在企业区段[0,1]画弧仅仅一种方法,也有许多其它的形式能够画弧,例如把区段[0,2 32-1]做为一个圆,随后用hash()函数计算服务项目连接点的hash()值。的hash()涵数转化成的值也需要在0 –( 2 32-1)的范畴内。

这儿大家就以[0,1]为例子来介绍一下。

大家以3个服务项目连接点为例子来开展表明php编码规范-php网页编程教程-第2张图片大家以三个服务项目连接点为例子开展表明。

一致性哈希优化算法连接点

这三个连接点任意的规划在这个圆上边。如今假定自己有一条数据信息(key,value)必须储存,下面要做的便是将这一条数据信息根据一样的方式投射到圆上边。php编码规范-php网页编程教程-第3张图片这三个连接点随机分布在圆上。如今,假定大家有一个数据信息(键,值)要储存。下一步是以一样的形式将这一段数据信息投射到一个圆上。

统一hash算法投射。

随后从功能键所属的圆上的部位逐渐,顺时针方向寻找服务项目连接点的部位,寻找的第一个服务项目连接点便是要储存的连接点。因而,该数据信息将被储存在服务项目连接点1上。

同样,当有其余的(key,value)对必须储存的情况下,也是依照里面的形式进行服务项目连接点的挑选。php编码规范-php网页编程教程-第4张图片相近地,当有别的(键,值)对必须储存时,服务项目连接点的挑选也依照以上方式开展。

统一hash算法多种投射。

如今大家一起来看看这一方式能不能满足大家刚刚提及的水平扩大的难题。

假定大家必须提升一个服务项目连接点3php编码规范-php网页编程教程-第5张图片假定大家必须加上一个服务项目连接点3。

一致性哈希优化算法提升服务项目连接点。

从图中中,我们可以见到仅有key1会变更其储存服务项目连接点。针对绝大多数数据信息,依然会寻找初始连接点。因而,针对有n个服务项目连接点的群集,当服务项目连接点较多时,一条数据信息的几率仅有1/(n 1),这将更改其储存的服务项目连接点。这一几率比被除数法获得的几率小得多。一样,降低一个服务项目连接点,提升一个服务项目连接点的机理是一样的,每一条数据信息再选服务项目连接点的几率是1/(n-1)。这一几率也不大。

使我们简易用php代码完成这一全过程。

$nodes = array('192.168.5.201','192.168.5.102','192.168.5.111');$keys = array('onmpw', 'jiyi', 'onmpw_key', 'jiyi_key', 'www','www_key','key1');$buckets = array(); //连接点的hash词典$maps = array(); //储存key和连接点间的投射关联/** * 转化成连接点词典 —— 使连接点遍布在企业区段[0,1)的圆内 */foreach( $nodes as $key) {$crc = crc32($key)/pow(2,32); // CRC値$buckets[] = array('index'=>$crc,'node'=>$key);}/* * 依据数据库索引开展排列 */sort($buckets);/* * 对每一个key开展hash测算,寻找其在圆上的部位 * 随后在该部位逐渐依顺时针寻找第一个服务项目连接点 */foreach($keys as $key){$flag = false; //表明是不是有寻找服务项目连接点$crc = crc32($key)/pow(2,32);//测算key的hash值for($i = 0; $i < count($buckets); $i ){ if($buckets[$i]['index'] >$crc){ /* *由于桶早已排列*,数据库索引超过键哈希值的第一个连接点是要寻找的连接点*/$ maps[$ key]= $ bucket[$ I][' node '];$ flag = true摆脱;}}if(!假如找不着$flag){ //则应用bucket中的第一个服务项目连接点$ maps[$ key]= $ bucket[0][' node '];} } foreach($ map as $ key = > $ val){ echo $ key。'=>'.$val,"
";}此程序执行的結果如下所示。

onmpw = > 192 . 168 . 5 . 102 jiyi = > 192 . 168 . 5 . 201 nmpw _ key = > 192 . 168 . 5 . 201 jiyi _ key = > 192 . 168 . 5 . 102 www = > 192 . 168 . 5 . 201 www _ key = > 192 . 168 . 5 . 201 key1 = > 192 . 168 . 5 . 111

随后大家加上一个服务项目连接点,并改动编码如下所示。

$nodes = array('192.168.5.201','192.168.5.102','192.168.5.111','192.168.5.11');

别的编码维持不会改变,再次使用的結果如下所示。

onmpw = > 192 . 168 . 5 . 102 jiyi = > 192 . 168 . 5 . 201 nmpw _ key = > 192 . 168 . 5 . 11 jiyi _ key = > 192 . 168 . 5 . 102 ww = > 192 . 168 . 5 . 201 www _ key = > 192 . 168 . 5 . 201 key1 = > 192 . 168 . 5 . 111

我们可以见到,仅有onmpw _ key重新选择了服务项目连接点。别的是初始连接点。

在这儿,我们可以见到击中几率远超被除数法。这解决了大家已经碰到的难题吗?

实际上,都还没。由于这种值的遍布终究并不是那麼的匀称。在系统软件中有可能这种服务项目连接点遍布十分的集中化,这很有可能造成的状况便是各种的key都投射到在其中的一个或是好多个连接点上边,剩余的服务项目连接点也没有被使用。尽管这并不是什么很严重的难题,那为何我们要消耗就算仅仅一台网络服务器呢。php编码规范-php网页编程教程-第6张图片事实上,都还没。由于这种熟知的遍布终究并不是那麼匀称。有可能这种服务项目连接点在系统软件中聚集遍布,很有可能造成全部的密匙都投射到一个或好多个连接点,剩余的服务项目连接点不被应用的状况。尽管这不是一个比较严重的难题,但大家为何要消耗就算一台网络服务器呢?

一致性哈希优化算法数据

大家看,这类状况就导致了数据信息集中化在一个服务项目连接点上边,导致了其他服务项目连接点的消耗。那如何解决这个问题呢?大家就又琢磨出了一种新的方法:便是为每一个连接点创建虚似的连接点。是什么意思呢?就是针对连接点j,为其创建m个仿制品。这m个拷贝出去的框架都根据hash()涵数得到不一样的hash值,可是每一个虚似连接点储存的连接点信息内容全是连接点j的。随后这种虚似连接点都是会任意的分散在圆上边。举个例子而言,大家有两个服务项目连接点。而且为每一个连接点都复制三个虚似连接点。这种连接点(包含虚似连接点都任意的分散在圆上边)php编码规范-php网页编程教程-第7张图片我们可以见到,这类状况造成数据信息集中化在一个服务项目连接点上,造成别的服务项目连接点的消耗。如何解决这个问题?大家想到了一个新方式:为每一个连接点建立虚似连接点。你什么意思?换句话说,针对连接点j,为其创建m个团本。m个拷贝的框架都根据hash()涵数获得不一样的哈希值,但每一个虚似连接点储存的连接点信息内容都归属于连接点J..随后这种虚似连接点随机分布在圆上。比如,大家有两个服务项目连接点。并为每一个连接点拷贝三个虚似连接点。这种连接点(包含虚似连接点)随机分布在圆上。

一致hash算法的分布均匀。

服务项目连接点好像分布均匀在圆形上。实际上,总的来说,它是对以上方式的轻度改善——将一些虚似连接点拷贝到每一个结点上。

因而,大家的编码不用改动过多。为了更好地形象化地见到编码,我将在这儿列举全部编码。

$nodes = array('192.168.5.201','192.168.5.102','192.168.5.111');$keys = array('onmpw', 'jiyi', 'onmpw_key', 'jiyi_key', 'www','www_key','key1');//加上的自变量 改动的地区$replicas = 160; //每一个连接点的拷贝的数量$buckets = array(); //连接点的hash词典$maps = array(); //储存key和连接点间的投射关联/** * 转化成连接点词典 —— 使连接点遍布在企业区段[0,1)的圆内 */foreach( $nodes as $key) { //改动的地区 for($i=1;$i$crc,'node'=>$key); }}/* * 依据数据库索引开展排列 */sort($buckets);/* * 对每一个key开展hash测算,寻找其在圆上的部位 * 随后在该部位逐渐依顺时针寻找第一个服务项目连接点 */foreach($keys as $key){$flag = false; //表明是不是有寻找服务项目连接点$crc = crc32($key)/pow(2,32);//测算key的hash值for($i = 0; $i < count($buckets); $i ){ if($buckets[$i]['index'] >$crc){ /* *由于桶早已排列*,数据库索引超过键哈希值的第一个连接点是要寻找的连接点*/$ maps[$ key]= $ bucket[$ I][' node '];$ flag = true摆脱;} } if(!假如找不着$flag){ //则应用bucket中的第一个服务项目连接点$ maps[$ key]= $ bucket[0][' node '];} } foreach($ map as $ key = > $ val){ echo $ key。'=>'.$val,"
";}这种变更已在编码中标明。由此可见改动的位置或是非常少的。

在这里一点上,我坚信所有人都应当对一致hach有一个清楚的了解。hash算法运用普遍,如memcache群集,Nginx加载等。

评论(0条)

刀客源码 游客评论