您好,登錄后才能下訂單哦!
<?php /** * 一致性hahs實現(xiàn)類 * */ class FlexiHash{ /** * var int * 虛擬節(jié)點 */ private $_replicas = 200; /** * 使用hash方法 */ private $_hasher = null; /** * 真實節(jié)點計數(shù)器 * */ private $_targetCount = 0; /** * 位置對應(yīng)節(jié)點,用戶lookup中根據(jù)位置確定要訪問的節(jié)點 */ private $_positionToTarget = array(); /** * 節(jié)點對應(yīng)位置,用于刪除節(jié)點 */ private $_targetToPositions = array(); /** * 是否已排序 */ private $_positionToTargetSorted = false; /** * @ $hasher hash方法 * @ $replicas 虛擬節(jié)點的個數(shù) * * 確定要使用的hash方法和虛擬的節(jié)點數(shù),虛擬節(jié)點越多,分布越均勻,但程序的分布式運算越慢 */ public function __construct(FlexiHash_Hasher $hasher=null, $replicas = null){ // hash方法 $this->_hasher = $hasher?$hasher: new FlexiHash_Crc32Hasher(); // 虛擬節(jié)點的個數(shù) if (!empty($replicas)){ $this->_replicas = $replicas; } } /** * 增加節(jié)點,根據(jù)虛擬節(jié)點數(shù),把節(jié)點分布到更多的虛擬位置上 */ public function addTarget($target){ if (isset($this->_targetToPositions[$target])) { throw new FlexiHash_Exception("Target $target already exists."); } $this->_targetToPositions[$target] = array(); for ($i = 0; $i < $this->_replicas; $i++) { // 根據(jù)規(guī)定的方法hash $position = $this->_hasher->hash($target.$i); // 虛擬節(jié)點對應(yīng)的真實的節(jié)點 $this->_positionToTarget[$position] = $target; // 真實節(jié)點包含的虛擬節(jié)點 $this->_targetToPositions[$target][] = $position; } $this->_positionToTargetSorted = false; // 真實節(jié)點個數(shù) $this->_targetCount++; return $this; } /** * 添加多個節(jié)點 * */ public function addTargets($targets){ foreach ($targets as $target){ $this->addTarget($target); } return $this; } /** * 移除某個節(jié)點 * */ public function removeTarget($target){ if (!isset($this->_targetToPositions[$target])){ throw new FlexiHash_Exception("target $target does not exist\n"); } foreach($this->_targetToPositions[$target] as $position){ unset($this->_positionToTarget[$position]); } unset($this->_targetToPositions[$target]); $this->_targetCount--; return $this; } /** * 獲取所有節(jié)點 * */ public function getAllTargets(){ return array_keys($this->_targetToPositions); } /** * 根據(jù)key查找hash到的真實節(jié)點 * */ public function lookup($resource){ $targets = $this->lookupList($resource, 1); if (empty($targets)){ throw new FlexiHash_Exception("no targets exist"); } return $targets[0]; } /** * 查找資源存在的節(jié)點 * * 描述:根據(jù)要求的數(shù)量,返回與$resource哈希后數(shù)值相等或比其大并且是最小的數(shù)值對應(yīng)的節(jié)點,若不存在或數(shù)量不夠,則從虛擬節(jié)點排序后的前一個或多個 */ public function lookupList($resource, $requestedCount){ if (!$requestedCount) { throw new FlexiHash_Exception('Invalid count requested'); } if (empty($this->_positionToTarget)) { return array(); } // 直接節(jié)點只有一個的時候 if ($this->_targetCount == 1 ){ return array_unique(array_values($this->_positionToTarget)); } // 獲取當(dāng)前key進行hash后的值 $resourcePosition = $this->_hasher->hash($resource); $results = array(); $collect = false; $this->_sortPositionTargets(); // 查找與$resourcePosition 相等或比其大并且是最小的數(shù) foreach($this->_positionToTarget as $key => $value){ if (!$collect && $key > $resourcePosition){ $collect = true; } if ($collect && !in_array($value, $results)){ $results[] = $value; } // 找到$requestedCount 或個數(shù)與真實節(jié)點數(shù)量相同 if (count($results) == $requestedCount || count($results) == $this->_targetCount){ return $results; } } // 如數(shù)量不夠或者未查到,則從第一個開始,將$results中不存在前$requestedCount-count($results),設(shè)置為需要的節(jié)點 foreach ($this->_positionToTarget as $key => $value){ if (!in_array($value, $results)){ $results[] = $value; } if (count($results) == $requestedCount || count($results) == $this->_targetCount){ return $results; } } return $results; } /** * 根據(jù)虛擬節(jié)點進行排序 */ private function _sortPositionTargets(){ if (!$this->_positionToTargetSorted){ ksort($this->_positionToTarget, SORT_REGULAR); $this->_positionToTargetSorted = true; } } }// end class /** * hash方式 */ interface FlexiHash_Hasher{ public function hash($string); } class FlexiHash_Crc32Hasher implements FlexiHash_Hasher{ public function hash($string){ return sprintf("%u",crc32($string)); } } class FlexiHash_Md5Hasher implements FlexiHash_Hasher{ public function hash($string){ return substr(md5($string), 0, 8); } } class FlexiHash_Exception extends Exception{ } $runData['BEGIN_TIME'] = microtime(true); $key="lihuibin"; for($i=0;$i<10;$i++) { $targetsArray = array( "127.0.0.1:11211", "127.0.0.1:11212", "127.0.0.1:11213", "127.0.0.1:11214", #"127.0.0.1:11218" ); $flexiHashObj = new FlexiHash(new FlexiHash_Crc32Hasher(),1); $result = $flexiHashObj->addTargets($targetsArray); $key=$key."$i"; $targets = $flexiHashObj->lookup($key); var_dump($targets); #$key = md5(mt_rand()); #$targets = $flexiHashObj->lookup($key); #var_dump($targets); } echo "一致性hash:"; var_dump(number_format(microtime(true) - $runData['BEGIN_TIME'],6)); exit; $runData['BEGIN_TIME'] = microtime(true); $m= new Memcache; $m->connect('127.0.0.1', 11211); for($i=0;$i<10000;$i++) { $key = md5(mt_rand()); $b = $m->set($key, time(), 0, 10); } echo "單臺機器:"; var_dump(number_format(microtime(true) - $runData['BEGIN_TIME'],6)); ?>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。