一致性hash在分布式缓存中的应用

Consistent Hashing 一致性哈希算法
小计:一致性hash在分布式缓存中的应用可以在服务器拓扑结构,添加机器发生变化时,影响最小,避免大量的缓存失效,都落在数据硬件上,从小导致当机,只影响到添加机器的后面一台机器
今天看豆瓣的架构PPT,其中有谈到Consistent Hashing的算法,网上搜了下,发现这方面的介绍也不算多。

通常比较常用的使用地方就是memcache分布式的时候,例如我有三台memcache,那么普通的hash算法,直接用你要取的key的hash值模取memcache的数量。

server = hash(key) mod server num;

但是如果要增加一台,那么将会有大量的缓存信息失效。所以更好的办法Consistent Hashing. 

Consistent hashing算法:环状结构。虚拟节点来替换实体节点被分配到环状某一位置上(根据处理能力不同可以将一个实体节点映射到多个虚拟节点上)。主键为key的节点position = hash(key),在环上按照顺时针查找value大于position的第一个虚拟节点,由它对应的实体节点处理。下图中k就优先由虚拟节点 B来处理。



按照我的理解方式 就是将所有的cache服务器的标识分别hash到的值分布到0-pow(2,32)中. 然后将你要取的key的hash值进行比较。取第一个大于key的hash值的服务器。 如果从0-pow(2,32)也没有找到,那么则取最小hash值的服务器。

例如 上图中, 服务器 a 的hash值 为 1, b的hash值为 10, c的hash值为20, 我们取 key K 的hash值为5的位置,发现key K 大于 a 小于 b , 那么key k就存放于服务器b上, 如果 我们取 key x 的hash值为30的位置,发现 a,b,c三个服务器的hash值都小于 key x的hash值 , 那么 我们取 a 服务器作为存放服务器。

这样的存放方法,只会影响你最后一台服务器存放的key.而不会像取模方法的全局影响。

当然这样取key的效率就没有取模的高了,至于采用哪种方法,还是要根据你当前业务的规模来选择的。

另附上简单的算法

<?php

function consistent_hash_key($key,$servers){
   if(empty($servers)){
       return false;
   }
   $hash_serv = array();
   $hash_key = sprintf("%u\n",crc32($key));
   foreach ($servers as $server){
       $hash_serv[sprintf("%u",crc32($server))] = $server;
   }
   
   ksort($hash_serv,SORT_REGULAR);
   
   if(count($hash_serv) == 1){
       return array_pop($hash_serv);
   }
   $maxHash = pow(2,32);
   foreach ($hash_serv as $k => $v){
       if($hash_key < $k){
           return $v;
       }
   }
   return array_shift($hash_serv);
}

for ($i=0;$i<100;$i++){
   echo consistent_hash_key('s:'.$i,array('a','b','c','d','e'))."\t".consistent_hash_key('s:'.$i,array('a','b','c','d','e','f'))."\n";
}
?>




 HRegion是Hbase中分布式存储和负载均衡的最小单元。最小单元就表示不同的Hregion可以分布在不同的HRegion server上。但一个Hregion是不会拆分到多个server上的。

猜你喜欢

转载自xubindehao.iteye.com/blog/1391460
今日推荐