zoukankan      html  css  js  c++  java
  • Memcached 一致性hash分布式算法

      1 <?php
      2 
      3     interface HashWay{
      4         public function hash($string);
      5     }
      6 
      7     class Md5HashWay implements HashWay{
      8         public function hash($string){
      9             return md5($string,0,8);
     10         }
     11     }
     12 
     13     class Crc32HashWay implements HashWay{
     14         public function hash($string){
     15             return crc32($string);
     16         }
     17     }
     18 
     19     class HashException extends Exception{
     20 
     21     }
     22 
     23     class ConsistentHash{
     24         //每一台memcached服务器的虚拟节点个数
     25         private $_replicas = 64;
     26         //表示memcached服务器的数量
     27         private $_targetCount = 0;
     28         //虚拟节点散列用到的hash算法
     29         private $_hasher = null;
     30         //一台memcached服务器对应的虚拟节点
     31         private $_targetToPostion = array();
     32         //虚拟节点对应memcached
     33         private $_postionToTarget = array();
     34         //是否排序
     35         private $_postionToTargetSorted = false;
     36 
     37 
     38         //构造函数,确定hasher的方法,已经虚拟节点的个数
     39         public function __construct(HashWay $hash = null,$replicas = null){
     40             $this->_hasher = $hash ? $hash : new Crc32HashWay();
     41             if(!empty($replicas))$this->_replicas = intval($replicas);
     42         }
     43 
     44         //增加一台服务器的操作
     45         public function addTarget($target){
     46             if(isset($this->targetToPostion[$target])){throw new HashException("$target exists");}
     47             
     48             //如果这台服务器没有存在,则给这台服务器去生成虚拟节点
     49             for($i = 0 ; $i < $this->_replicas; $i++){
     50                 $postion = $this->_hasher->hash($target.$i);
     51                 //虚拟节点指向target
     52                 $this->_postionToTarget[$postion] = $target;
     53                 //每一个服务器对应的虚拟节点
     54                 $this->_targetToPostion[$target][] = $postion;
     55             }
     56 
     57             $this->_targetCount++;
     58 
     59             //每次增加memcached服务器过来,虚拟节点都会混乱,必须排序来解决问题
     60             $this->_postToTargetSorted = false;
     61             return $this;
     62         }
     63 
     64         //增加多台memcached服务器
     65         public function addTargets($targets){
     66             if(is_array($targets) && !empty($targets)){
     67                 foreach ($targets as $key => $value) {
     68                     $this->addTarget($value);
     69                 }
     70             }
     71         }
     72 
     73         //删除一台服务器的操作
     74         public function removeTarget($target){
     75             if(!isset($this->_targetToPostion[$target])){throw new HashException("$target not exists");}
     76         
     77             //现在进行删除服务器的操作
     78             foreach ($this->_targetToPostion[$target] as $key => $value) {
     79                 //根据虚拟节点数组,来删除指向target的数组
     80                 if(isset($this->_postionToTarget[$value])){
     81                     unset($this->_postionToTarget[$value]);
     82                 }
     83             }
     84             unset($this->_targetToPostion[$target]);
     85             $this->_targetCount--;
     86             return $this;
     87         }
     88 
     89 
     90         //得到全部的memcached服务器
     91         public function getAllTargets(){
     92             return array_keys($this->_targetToPostion);
     93         }
     94 
     95         //查找存储的服务器
     96         public function lookUp($resource){
     97             $result = $this->lookUpList($resource);
     98             return $this->_postionToTarget[current($result)];
     99         }
    100         
    101         //lookup函数返回一个环,数组0表示的是顺时针最近的memcached服务器
    102         public function lookUpList($resource){
    103 
    104             if($this->_targetCount == 0){
    105                 return array();
    106             }
    107 
    108             //如果只有一个服务器,则返回
    109             if($this->_targetCount == 1){
    110                 return array_unique(array_values($this->_postionToTarget));
    111             }
    112             
    113 
    114             //如果没有找到一个服务器
    115             //1对虚拟节点进行排序
    116             $this->_sortedPostToTargets();
    117 
    118 
    119             //2对查找的resource进行hash
    120             $hashresource = $this->_hasher->hash($resource);
    121 
    122             //3对虚拟节点查找
    123             $flag = false;
    124             $result = array();
    125 
    126             //4优先查找服务器,取得顺时针最近的服务器
    127             foreach ($this->_postionToTarget as $key => $value) {
    128                 if(!$flag && $key > $hashresource){
    129                     $flag = true;
    130                 }
    131 
    132                 if($flag == true && !in_array($key,$result)){
    133                     $result[] = $key;
    134                 }
    135 
    136                 if(count($result) == $this->_targetCount){
    137                     return $result;
    138                 }
    139             }
    140 
    141             //5如果没有在顺时针取得服务器,那就重新再来一遍
    142             foreach ($this->_postionToTarget as $key => $value) {
    143                 if(!in_array($key,$result)){
    144                     $result[] = $key;
    145                 }
    146 
    147                 if(count($result) == $this->_targetCount){
    148                     return $result;
    149                 }
    150             }
    151 
    152             return $result;
    153         }
    154 
    155         //对虚拟节点进行排序
    156         private function _sortedPostToTargets(){
    157             if(!$this->_postionToTargetSorted){
    158                 ksort($this->_postionToTarget,SORT_REGULAR);
    159                 $this->_postionToTargetSorted = true;
    160             }
    161         }
    162     }
    163     
    164     
    165     $a = new ConsistentHash;
    166     //添加了两台主机
    167     $a->addTarget('192.168.1.1')->addTarget('192.168.1.2')->addTarget('192.168.1.3')->addTarget('192.168.1.4');
    168     print_r($a->getAllTargets());
    169     
    170     echo "<br/>";
    171     $result = array();
    172     for($i = 0; $i < 100 ; $i++){
    173         if(!isset($result[$a->lookUp($i)])){
    174             $result[$a->lookUp($i)] = 1;
    175         }else{
    176             $result[$a->lookUp($i)] ++;
    177         }
    178     }
    179     
    180     print_r($result);
    181     
    182 ?>
    Array ( [0] => 192.168.1.1 [1] => 192.168.1.2 [2] => 192.168.1.3 [3] => 192.168.1.4 ) 
    Array ( [192.168.1.2] => 13 [192.168.1.1] => 44 [192.168.1.3] => 28 [192.168.1.4] => 15 )

      这边只是简单的代码实现,用于解决分布均衡问题

    学习地址:http://blog.csdn.net/cywosp/article/details/23397179

         http://blog.sina.com.cn/s/blog_3fde8252010147j5.html

         好像忘记添加一个链接了,有原代码一致性hash的链接,我就是看懂,然后自己写了下,不喜勿喷。

           

  • 相关阅读:
    ASP.NET 表单验证 Part.1(理解表单验证)
    Silverlight 简介 Part.3(设计 Siverlight 页面)
    ASP.NET 成员资格 Part.3(LoginStatus、LoginView、PasswordRecovery)
    ASP.NET 网站部署 Part.1(安装IIS、复制文件部署网站)
    ASP.NET Dynamic Data Part.1(创建动态数据应用程序)
    ASP.NET 安全模型 Part.2(SSL)
    ASP.NET MVC Part.2(扩展基本的 MVC 应用程序)
    ASP.NET 网站部署 Part.2(使用 Web 部署)
    开发高级 Web 部件
    创建 Web 部件(WebPart 类、简单的 Web 部件)
  • 原文地址:https://www.cnblogs.com/zafuacm/p/4229380.html
Copyright © 2011-2022 走看看