PHP實現一致性hash

<?php /** * 一致性哈希實現接口 * Interface ConsistentHash */ interface ConsistentHash { //將字符串轉爲hash值 public function cHash(string $str): int; //添加一臺服務器到服務器列表中 public function addServer(string $serverHost); //從服務器刪除一臺服務器 public function removeServer(string $serverHost); //在當前的服務器列表中找到合適的服務器存放數據 public function lookup(string $key); } /** * 具體一致性哈希實現 * author chenqionghe * Class MyConsistentHash */ class MyConsistentHash implements ConsistentHash { public $serverList = []; //服務器列列表 public $virtualPos = []; //虛擬節點的位置 public $virtualPosNum = 5; //每個節點對應5個虛節點 /** * 將字符串轉換成32位無符號整數hash值 * @param $str * @return int */ public function cHash(string $str): int { $str = md5($str); return sprintf('%u', crc32($str)); } /** * 添加一臺服務器到服務器列表中 * @param $server 服務器IP地址 * @return bool */ public function addServer(string $server) { if (!isset($this->serverList[$server])) { //增加虛擬節點 for ($i = 0; $i < $this->virtualPosNum; $i++) { $pos = $this->cHash($server . '#' . $i); //存放虛擬節點存放的對應的服務器 $this->virtualPos[$pos] = $server; //存放單臺服務器包含的所有節點 $this->serverList[$server][] = $pos; } //虛擬節點根據位置排序 ksort($this->virtualPos, SORT_NUMERIC); } } /** * 移除一臺服務器(循環所有的虛節點,刪除值爲該服務器地址的虛節點) * @param $key * @return bool */ public function removeServer($key) { if (isset($this->serverList[$key])) { //刪除一臺服務器上的所有虛節點 foreach ($this->serverList[$key] as $pos) { unset($this->virtualPos[$pos]); } //刪除對應服務器 unset($this->serverList[$key]); } } /** * 在當前的服務器列表中找到合適的服務器存放數據 * @param $key 鍵名 * @return mixed 返回服務器IP地址 */ public function lookup(string $key) { $point = $this->cHash($key);//落點的hash值 $finalServer = current($this->virtualPos);//先取圓環上最小的一個節點當成結果(數組的第一個索引單元) //找到虛擬節點最接近的服務器 foreach ($this->virtualPos as $pos => $server) { if ($point <= $pos) { $finalServer = $server; break; } } reset($this->virtualPos);//重置圓環的指針爲第一個(重置數組的指針) return $finalServer; } } $hashServer = new MyConsistentHash(); $hashServer->addServer('192.168.1.1'); $hashServer->addServer('192.168.1.2'); $hashServer->addServer('192.168.1.3'); $hashServer->addServer('192.168.1.4'); $hashServer->addServer('192.168.1.5'); $hashServer->addServer('192.168.1.6'); $hashServer->addServer('192.168.1.7'); $hashServer->addServer('192.168.1.8'); $hashServer->addServer('192.168.1.9'); $hashServer->addServer('192.168.1.10'); echo "增加十臺服務器192.168.1.1~192.168.1.10<br />"; echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />'; echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />'; echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />'; echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />'; echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />'; echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />'; echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />'; echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />'; echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />'; echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />'; echo "<pre>"; print_r($hashServer->virtualPos);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章