| <?php class FlexiHash{ private $_replicas = 200; private $_hasher = null; private $_targetCount = 0; private $_positionToTarget = array(); private $_targetToPositions = array(); private $_positionToTargetSorted = false; public function __construct(FlexiHash_Hasher $hasher=null, $replicas = null){$this->_hasher = $hasher?$hasher: new FlexiHash_Crc32Hasher();if (!empty($replicas)){$this->_replicas = $replicas;}} 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++) {$position = $this->_hasher->hash($target.$i);$this->_positionToTarget[$position] = $target;$this->_targetToPositions[$target][] = $position;}$this->_positionToTargetSorted = false;$this->_targetCount++;return $this;} public function addTargets($targets){foreach ($targets as $target){$this->addTarget($target);}return $this;} 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;} public function getAllTargets(){return array_keys($this->_targetToPositions);} public function lookup($resource){$targets = $this->lookupList($resource, 1);if (empty($targets)){throw new FlexiHash_Exception("no targets exist");}return $targets[0];} public function lookupList($resource, $requestedCount){if (!$requestedCount) {throw new FlexiHash_Exception('Invalid count requested');}if (empty($this->_positionToTarget)) {return array();}if ($this->_targetCount == 1 ){return array_unique(array_values($this->_positionToTarget));}$resourcePosition = $this->_hasher->hash($resource);$results = array();$collect = false;$this->_sortPositionTargets();foreach($this->_positionToTarget as $key => $value){if (!$collect && $key > $resourcePosition){$collect = true;}if ($collect && !in_array($value, $results)){$results[] = $value;}if (count($results) == $requestedCount || count($results) == $this->_targetCount){return $results;}}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;} private function _sortPositionTargets(){if (!$this->_positionToTargetSorted){ksort($this->_positionToTarget, SORT_REGULAR);$this->_positionToTargetSorted = true;}}} 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));?> |