Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1204771
  • 博文数量: 252
  • 博客积分: 5421
  • 博客等级: 大校
  • 技术积分: 2418
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-17 12:59
文章分类

全部博文(252)

文章存档

2017年(3)

2016年(18)

2015年(31)

2014年(18)

2013年(7)

2012年(8)

2011年(12)

2010年(30)

2009年(32)

2008年(57)

2007年(36)

分类: PHP

2015-07-09 18:31:13


  1. <?php
  2. /**
  3.  * 对服务器进行一致性hash分布算法
  4.  */
  5. class HashRing
  6. {
  7.     private $servers = array();
  8.     private $nodeList = array();
  9.     private $nodeHashList = array();
  10.     private $nodeTotalNum = 0;
  11.     private $virtualNodeNum = 32;
  12.     private $keyHash = '';

  13.     public function __construct($servers)
  14.     {
  15.         $this->servers = $servers;
  16.         foreach ($servers as $server) {
  17.             for ($i = 0; $i < $this->virtualNodeNum; $i++) {
  18.                 $this->nodeList[sprintf("%u", crc32($server.'-'.$i))] = array($server, $i);
  19.             }
  20.         }
  21.         ksort($this->nodeList);
  22.         $this->nodeHashList = array_keys($this->nodeList);
  23.     }

  24.     private function getNodeIndex($key)
  25.     {
  26.         $this->keyHash = sprintf("%u", crc32($key));
  27.         if ($this->keyHash > end($this->nodeHashList)) {
  28.             $this->keyHash = $this->keyHash % end($this->nodeHashList);
  29.         }
  30.         if ($this->keyHash <= reset($this->nodeHashList)) {
  31.             return 0;
  32.         }
  33.         $this->nodeTotalNum = count($this->nodeHashList);
  34.         return $this->binaryChopIndex(0, $this->nodeTotalNum);
  35.     }

  36.     private function binaryChopIndex($l=0, $r=0)
  37.     {
  38.         if ($l < $r) {
  39.             $avg = intval(($l+$r) / 2);
  40.             if ($this->nodeHashList[$avg] == $this->keyHash) {
  41.                 return $avg;
  42.             } elseif ($this->keyHash < $this->nodeHashList[$avg] && ($avg > 0)) {
  43.                 return $this->binaryChopIndex($l, $avg-1);
  44.             } else {
  45.                 return $this->binaryChopIndex($avg+1, $r);
  46.             }
  47.         } else {
  48.             return $l;
  49.         }
  50.     }

  51.     public function getServersByKey($key, $num=1)
  52.     {
  53.         $index = $this->getNodeIndex($key);
  54.         $server = $this->nodeList[$this->nodeHashList[$index]];
  55.         if ($num == 1) {
  56.             return $server[0];
  57.         }
  58.         if ($num >= count($this->servers)) {
  59.             $num = count($this->servers);
  60.         }
  61.         $result = array($server[0]);
  62.         for ($i=$index+1; true; $i++) {
  63.             if ($i >= $this->nodeTotalNum) {
  64.                 $i = 0;
  65.             }
  66.             $nextServer = $this->nodeList[$this->nodeHashList[$i]];
  67.             if (!in_array($nextServer[0], $result)) {
  68.                 $result[] = $nextServer[0];
  69.             }
  70.             if (count($result) == $num) {
  71.                 break;
  72.             }
  73.         }
  74.         return $result;
  75.     }
  76. }



  77. //示例
  78. $servers = array(
  79.     '127.0.0.1:11211',
  80.     '127.0.0.1:11212',
  81.     '127.0.0.1:11213',
  82.     '127.0.0.1:11214',
  83.     '127.0.0.1:11215'
  84. );
  85. $obj = new HashRing($servers);
  86. $servers = $obj->getServersByKey('testkey', 2);
  87. print_r($servers);
  88. echo "\n";

阅读(1144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~