生活随笔
收集整理的這篇文章主要介紹了
memcache分布式 [一致性hash算法] 的php实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
以前一般用的是最原始的hash取模做分布式,當生產過程中添加或刪除一臺memcache都會造成數據的全部失效,一致性hash就是為了解決這個問題,把失效數據降到最低,相關資料可以google一下!
php實現效率有一定的缺失,如果要高效率,還是寫擴展比較好
經測試,5個memcache,每個memcache生成100個虛擬節點,set加get1000次,與單個memcache直接set加get慢5倍,所以效率一般,有待優化!
實現過程:
- memcache的配置 ip+端口+虛擬節點序列號 做hash,使用的是crc32,形成一個閉環。
- 對要操作的key進行crc32
- 二分法在虛擬節點環中查找最近的一個虛擬節點
- 從虛擬節點中提取真實的memcache ip和端口,做單例連接
<?php/*** 一致性哈希memcache分布式,采用的是虛擬節點的方式解決分布均勻性問題,查找節點采用二分法快速查找* the last known user to change this file in the repository <$LastChangedBy: nash.xiong [ DISCUZ_CODE_0 ]gt;* @author nash.xiong <nash.xiong@gmail.com>* @copyright Copyright © 2003-2012 phpd.cn* @license */class memcacheHashMap {private $_node = array();private $_nodeData = array();private $_keyNode = 0;private $_memcache = null;//每個物理服務器生成虛擬節點個數 [注:節點數越多,cache分布的均勻性越好,同時set get操作時,也更耗資源,10臺物理服務器,采用200較為合理]private $_virtualNodeNum = 200; private function __construct() {/* 放入配置文件 */$config = 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:11215');if (!$config) throw new Exception('Cache config NULL');foreach ($config as $key => $value) {for ($i = 0; $i < $this->_virtualNodeNum; $i++) {$this->_node[sprintf("%u", crc32($value . '_' . $i))] = $value . '_' . $i;}}ksort($this->_node);}private function __clone(){}/*** 單例,保證只有一個實例*/static public function getInstance() {static $memcacheObj = null;if (!is_object($memcacheObj)) {$memcacheObj = new self();}return $memcacheObj;}/*** 根據key做一致性hash后連接到一臺物理memcache服務器* @param string $key*/private function _connectMemcache($key) {$this->_nodeData = array_keys($this->_node);$this->_keyNode = sprintf("%u", crc32($key));$nodeKey = $this->_findServerNode();//如果超出環,從頭再用二分法查找一個最近的,然后環的頭尾做判斷,取最接近的節點if ($this->_keyNode > end($this->_nodeData)) {$this->_keyNode -= end($this->_nodeData);$nodeKey2 = $this->_findServerNode();if (abs($nodeKey2 - $this->_keyNode) < abs($nodeKey - $this->_keyNode)) $nodeKey = $nodeKey2;}var_dump($this->_node[$nodeKey]);list($config, $num) = explode('_', $this->_node[$nodeKey]);if (!$config) throw new Exception('Cache config Error');if (!isset($this->_memcache[$config])) {$this->_memcache[$config] = new Memcache;list($host, $port) = explode(':', $config);$this->_memcache[$config]->connect($host, $port);}return $this->_memcache[$config];}/*** 采用二分法從虛擬memcache節點中查找最近的節點* @param unknown_type $m* @param unknown_type $b*/private function _findServerNode($m = 0, $b = 0) {$total = count($this->_nodeData);if ($total != 0 && $b == 0) $b = $total - 1;if ($m < $b){$avg = intval(($m+$b) / 2);if ($this->_nodeData[$avg] == $this->_keyNode) return $this->_nodeData[$avg];elseif ($this->_keyNode < $this->_nodeData[$avg] && ($avg-1 >= 0)) return $this->_findServerNode($m, $avg-1);else return $this->_findServerNode($avg+1, $b);}if (abs($this->_nodeData[$b] - $this->_keyNode) < abs($this->_nodeData[$m] - $this->_keyNode)) return $this->_nodeData[$b];else return $this->_nodeData[$m];}public function set($key, $value, $expire = 0) {return $this->_connectMemcache($key)->set($key, json_encode($value), 0, $expire);}public function add($key, $value, $expire = 0) {return $this->_connectMemcache($key)->add($key, json_encode($value), 0, $expire);}public function get($key) {return json_decode($this->_connectMemcache($key)->get($key), true);}public function delete($key) {return $this->_connectMemcache($key)->delete($key);}}$runData['BEGIN_TIME'] = microtime(true);//測試一萬次set加getfor($i=0;$i<10000;$i++) {$key = md5(mt_rand());$b = memcacheHashMap::getInstance()->set($key, time(), 10);}var_dump(number_format(microtime(true) - $runData['BEGIN_TIME'],6));$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);}var_dump(number_format(microtime(true) - $runData['BEGIN_TIME'],6));
//測試結果,采用一致性哈希分布效率比原生單臺速度相差5倍左右
轉載于:https://www.cnblogs.com/zxz1987/p/6515895.html
總結
以上是生活随笔為你收集整理的memcache分布式 [一致性hash算法] 的php实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。