一臺Memcache通常不能滿足我們的需求,這就需要分布式部署。Memcached分布式部署方案通常會采用兩種方式,一種是普通Hash分布,一種是一致性Hash分布,本篇將以PHP作為客戶端,來分析兩種方案.
一、普通Hash分布:
- <?php
- function test($key='name'){
- $md5 = substr(md5($key), 0, 8);
- $seed = 31;
- $hash = 0;
- for($i=0; $i<8; $i++){
- $hash = $hash * $seed + ord($md5[$i]);
- }
- return $hash & 0x7FFFFFFF;
- }
- $memcacheList = array(
- array('host'=>'192.168.1.2', 'port'=>6379),
- array('host'=>'192.168.1.3', 'port'=>6379),
- array('host'=>'192.168.1.4', 'port'=>6379),
- array('host'=>'192.168.1.5', 'port'=>6379),
- );
- $key = 'username';
- $value = 'lane';
- //根據KEY獲取hash
- $hash = $this->test($key);
- $count = count($memcacheList);
- $memcache = $memcacheList[$hash % $count];
- $mc = new Memcached($memcache);
- $mc->set($key, $value);
- ?>
代碼很簡單,一個Hash函數,根據所需要的key,將他md5后取前8位,然后經過Hash算法返回一個整數,將這個整數對服務器總數求模,得到的就是服務器列表的編號,這種方式的缺點是服務器數量改變后,同一個key不同hash,將取不到值了.
二、一致性Hash分布
一致性Hash盡管也會造成數據的丟失,但是損失是最小的,將2的32次方-1想象成一個圓環,服務器列表在上面排列,根據key通過hash算法求得在圓環上的位置,那么所需要的服務器的位置在key的位置前面最近的一個(順時針).
- <?php
- class FlexiHash{
- //服務器列表
- private $serverList = array();
- //是否排序
- private $isSort = false;
- /**
- * Description: Hash函數,將傳入的key以整數形式返回
- * @param string $key
- * @return int
- */
- private function myHash($key){
- $md5 = substr(md5($key), 0, 8);
- $seed = 31;
- $hash = 0;
- for($i=0; $i<8; $i++){
- $hash = $hash * $seed + ord($md5[$i]);
- }
- return $hash & 0x7FFFFFFF;
- }
- /**
- * Description: 添加新服務器
- * @param $server
- */
- public function addServer($server){
- $hash = $this->myHash($server);
- if(!isset($this->serverList[$hash])){
- $this->serverList[$hash] = $server;
- }
- $this->isSort = false;
- return true;
- }
- /**
- * Description: 刪除指定服務器
- * @param $server
- * @return bool
- */
- public function removeServer($server){
- $hash = $this->myHash($server);
- if(isset($this->serverList[$hash])){
- unset($this->serverList[$hash]);
- }
- $this->isSort = false;
- return true;
- }
- /**
- * Description: 根據要操作的KEY返回一個操作的服務器信息
- * @param $key
- * @return mixed
- */
- public function lookup($key){
- //將指定的KEYhash出一個整數
- $hash = $this->myHash($key);
- if($this->isSort !== true){
- krsort($this->serverList);
- $this->isSort = false;
- }
- foreach($this->serverList as $key=>$server){
- if($key <= $hash){
- return $server;
- }
- }
- return array_pop($this->serverList);
- } //開源軟件:Vevb.com
- }
- //使用方法
- $mc = new FlexiHash();
- $mc->addServer('192.168.1.2');
- $mc->addServer('192.168.1.3');
- $mc->addServer('192.168.1.4');
- $mc->addServer('192.168.1.5');
- echo 'KEY=key1時,操作的服務器為:'.$mc->lookup('key1').'<br>';
- echo 'KEY=key1時,操作的服務器為:'.$mc->lookup('key2').'<br>';
- echo 'KEY=key1時,操作的服務器為:'.$mc->lookup('key3').'<br>';
- echo 'KEY=key1時,操作的服務器為:'.$mc->lookup('key4').'<br>';
- echo 'KEY=key1時,操作的服務器為:'.$mc->lookup('key5').'<br>';
- ?>
|
新聞熱點
疑難解答