這次帶給大家PHP實作一致性Hash演算法步驟詳解,PHP實作一致性Hash演算法的注意事項有哪些,以下就是實戰案例,一起來看一下。
一致性雜湊演算法是分散式系統中常用的算法,為什麼要用這個演算法?
例如:一個分散式儲存系統,要將資料儲存到具體的節點(伺服器)上, 在伺服器數量不改變的情況下,如果採用普通的hash再對伺服器總數量取模的方法(如key%伺服器總數量),如果期間有伺服器宕機了或需要增加伺服器,問題就出來了。同一個key經過hash之後,再與伺服器總數量取模的結果跟之前的結果會不一樣,這就導致了先前保存資料的遺失。因此,引入了一致性Hash(Consistent Hashing)分佈演算法
把資料用hash函數(如md5,sha1),映射到一個圓環上,如上圖所示,資料在儲存時,先根據hash演算法算出key的hash值,對應到這個環中的位置,如k1對應圖中所示的位置同,然後沿著順時針方向找到伺服器節點B,然後把k1在存到B這個節點中。
如果B節點宕機了,則B上的資料就會落到C節點上,如下圖所示
一致性雜湊演算法的PHP實作
下面給一個介面/** * 一致性哈希实现接口 * Interface ConsistentHash */ interface ConsistentHash { //将字符串转为hash值 public function cHash($str); //添加一台服务器到服务器列表中 public function addServer($server); //从服务器删除一台服务器 public function removeServer($server); //在当前的服务器列表中找到合适的服务器存放数据 public function lookup($key); }這個介面分別定義了4個方法,cHash(將字串處理為hash值)、addServer(增加一台伺服器)、removeServer(移除一台伺服器)、lookup(找到一台伺服器來儲存資料)下面給出一個該介面的具體實作
/** * 具体一致性哈希实现 * author chenqionghe * Class MyConsistentHash */ class MyConsistentHash implements ConsistentHash { public $serverList = array(); //服务器列列表 public $virtualPos = array(); //虚拟节点的位置 public $virtualPosNum = 5; //每个节点对应5个虚节点 /** * 将字符串转换成32位无符号整数hash值 * @param $str * @return int */ public function cHash($str) { $str = md5($str); return sprintf('%u', crc32($str)); } /** * 在当前的服务器列表中找到合适的服务器存放数据 * @param $key 键名 * @return mixed 返回服务器IP地址 */ public function lookup($key) { $point = $this->cHash($key);//落点的hash值 $finalServer = current($this->virtualPos);//先取圆环上最小的一个节点当成结果 foreach($this->virtualPos as $pos=>$server) { if($point virtualPos);//重置圆环的指针为第一个 return $finalServer; } /** * 添加一台服务器到服务器列表中 * @param $server 服务器IP地址 * @return bool */ public function addServer($server) { if(!isset($this->serverList[$server])) { for($i=0; $ivirtualPosNum; $i++) { $pos = $this->cHash($server . '-' . $i); $this->virtualPos[$pos] = $server; $this->serverList[$server][] = $pos; } ksort($this->virtualPos,SORT_NUMERIC); } return TRUE; } /** * 移除一台服务器(循环所有的虚节点,删除值为该服务器地址的虚节点) * @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]); } return TRUE; } }然後, 讓我們來測試一下演算法
$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 '<hr>'; echo "移除一台服务器192.168.1.2<br>"; $hashServer->removeServer('192.168.1.2'); 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 '<hr>'; echo "移除一台服务器192.168.1.6<br>"; $hashServer->removeServer('192.168.1.6'); 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 '<hr>'; echo "移除一台服务器192.168.1.8<br>"; $hashServer->removeServer('192.168.1.8'); 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 '<hr>'; echo "移除一台服务器192.168.1.2<br>"; $hashServer->removeServer('192.168.1.2'); 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 '<hr>'; echo "增加一台服务器192.168.1.11<br>"; $hashServer->addServer('192.168.1.11'); 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 '<hr>';運行結果如下
17.1-16811212168.110增加十台伺服器192.168.1.1~192.168.1.10
key17 到#1812112168.110
儲存key1 到server :192.168.1.2
儲存key2 到server :192.168.1.1
儲存key3 到server :191668.192662.
儲存key4 到server :192.168.1.8
儲存key5 到server :192.168.1.9
儲存key6 到server :192.168.1.10
已經儲存到#key7 到server :192.168.1.7 儲存到被儲存到#key server :192.168.1.4
儲存key9 到server :192.168.1.7
儲存key10 到server :192.168.1.4
移除一台伺服器192.168.1.2
儲存key1 到server :1922168.192#key1 到server17. ##儲存key3 到server :192.168.1.1
儲存key3 到server :192.168.1.6
儲存key4 到server :192.168.1.8
儲存key5 到server :192.168.169.1.8
儲存key5 到server :192.168.11.server# :192.168.1.10
儲存key7 到server :192.168.1.7
儲存key8 到server :192.168.1.4
儲存key9 到server :192.168.1.7
##key10 到server :192.168.1.7
##192.server 儲存:1186:
186:186:##21. #移除一台伺服器192.168.1.6
儲存key1 到server :192.168.1.7
儲存key2 到server :192.168.1.1
儲存key3 到server :192.168.1.3
##key4 到 server: 192.168.1.8
保存key5 到server :192.168.1.9
保存key6 到server :192.168.1.10
保存key7 到server :192.168.1.7
保存key8 到server :1server :192.168.1.7
存檔儲存key9 到server :192.168.1.7
儲存key10 到server :192.168.1.4
移除一台伺服器192.168.1.8
儲存key1 到server :192.168.1.7
key2 到儲存key1 到server :192.168.1.7
key12 到server:68 .1.1
保存key3 到server :192.168.1.3
保存key4 到server :192.168.1.10
保存key5 到server :192.168.1.9
保存key6 到server :192.168.1. key7 到server :192.168.1.7
儲存key8 到server :192.168.1.4
儲存key9 到server :192.168.1.7
儲存key10 到server :192.168.168.1.7
儲存key10 到server :192.168.1.4#1686868.1.4#16868.1.4#168. 1.2
儲存key1 到server :192.168.1.7
儲存key2 到server :192.168.1.1
儲存key3 到server :192.168.1.3
儲存key4 儲存到server :192.168.168.1.3
儲存key4 到server :192.168.1.101151511592.168.1.到server :192.168.1.9
保存key6 到server :192.168.1.10
保存key7 到server :192.168.1.7
保存key8 到server :192.168.1.4
key9 到儲存key8 到server :192.168.1.4
19 到儲存key8 到server :192.168.1.4
19 到儲存key8
儲存key10 到server :192.168.1.4
增加一台伺服器192.168.1.11
儲存key1 到server :192.168.1.7
儲存key2 到server :192.168.1.1
key3 儲存到:192.168.1.11
儲存key4 到server :192.168.1.10
儲存key5 到server :192.168.1.9
儲存key6 到server :192.168.1.10
key17 到 168.192.168.1.10
17.server1681211212119.1212121.10
17.1-1681121212119.1017.1-1681121212121.10
17。 #儲存key8 到server :192.168.1.4儲存key9 到server :192.168.1.7
儲存key10 到server :192.168.1.4可以,看到,使用一致性哈希後,無認是增加伺服器還是減少伺服器都最大程度的保證了資料的完整性、均勻性.
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章! 推薦閱讀:
######thinkPHP框架自動填入原理與用法使用詳解############PHP裝飾器模式使用詳解###### #以上是PHP實作一致性Hash演算法步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

Hash操作//为hash表中的字段赋值。成功返回1,失败返回0。若hash表不存在会先创建表再赋值,若字段已存在会覆盖旧值。$ret=$redis->hSet('user','realname','jetwu');//获取hash表中指定字段的值。若hash表不存在则返回false。$ret=$redis->hGet('user','rea

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

在PHP中,可以利用implode()函数的第一个参数来设置没有分隔符,该函数的第一个参数用于规定数组元素之间放置的内容,默认是空字符串,也可将第一个参数设置为空,语法为“implode(数组)”或者“implode("",数组)”。

查找方法:1、用strpos(),语法“strpos("字符串值","查找子串")+1”;2、用stripos(),语法“strpos("字符串值","查找子串")+1”。因为字符串是从0开始计数的,因此两个函数获取的位置需要进行加1处理。

Laravel是目前最为流行的PHPweb框架之一,为开发人员提供了许多强大的功能和组件,其中LaravelHash也是其中之一。LaravelHash是一个用于密码散列的PHP库,其可以用于保护密码的安全,并使应用程序的用户数据更加安全。在本文中,我们将了解LaravelHash的工作原理以及如何使用它来对密码进行散列和验证。前置知识在学习Lara


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境