使用php实现一致性hash算法
hasher = isset($hasher) ? $hasher : new Crc32Hasher(); isset($replicas) && $this->replicas = $replicas; } public function addTarget($target, $weight = 1) { $positions = array(); $existPositions = array_keys($this->positionTargetMap); for ($i = 0; $i < $this->replicas * $weight; $i++) { //find an position not in exist positions $suffix = ''; do { $suffix .= $i; $position = $this->hasher->hash($target.''.$suffix); } while (in_array($position, $existPositions)); //record position's target $this->positionTargetMap[$position] = $target; //collect position $positions[] = $position; } //sort position ksort($this->positionTargetMap); //record target's positions $this->targetPositionsMap[$target] = $positions; } public function removeTarget($target) { if (!isset($this->targetPositionsMap[$target])) { throw new Exception('remove not exists target: '.$target); } $positions = $this->targetPositionsMap[$target]; //remove target's positions unset($this->targetPositionsMap[$target]); //remove position's target foreach ($positions as $position) { unset($this->positionTargetMap[$position]); } } public function lookup($resource) { return $this->lookupList($resource, 1)[0]; } public function lookupList($resource, $count) { if ($this->isTargetsEmpty()) { throw new Exception('lookup targets empty'); } if ($count > count($this->targetPositionsMap)) { throw new Exception('lookup targets not enough'); } $targetList = array(); $hash = $this->hasher->hash($resource); //find in the above positions foreach ($this->positionTargetMap as $position => $t) { if (count($targetList) == $count) { break; } if ($hash >= $position) { $targetList[] = $t; } } //find in the below positions if (count($targetList) < $count) { foreach ($this->positionTargetMap as $position => $t) { if (count($targetList) == $count) { break; } $targetList[] = $t; } } return $targetList; } public function isTargetsEmpty() { return count($this->targetPositionsMap) == 0; } public function addTargets($targets) { foreach ($targets as $target) { $this->addTarget($target); } } public function removeTargets($targets) { foreach ($targets as $target) { $this->removeTarget($target); } }}