classMemcachehash {Private $_node=Array(); Private $_nodedata=Array(); Private $_keynode= 0; Private $_memcache=NULL; //number of virtual nodes per physical server [Note: The more the number of nodes, the better the cache distribution uniformity, while the set get operation, but also more resource-intensive, 10 physical servers, using 200 more reasonable] Private $_virtualnodenum= 200; Private function__construct () {/*put the configuration file*/ $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 () {}/** Single case, guaranteed only one instance*/ Static Public functiongetinstance () {Static $MEMCACHEOBJ=NULL; if(!Is_object($MEMCACHEOBJ)) { $MEMCACHEOBJ=NewSelf (); } return $MEMCACHEOBJ; } /** * After a consistent hash based on key to connect to a physical memcache server * @param string $key*/ Private function_connectmemcache ($key) { $this->_nodedata =Array_keys($this-_node); $this->_keynode =sprintf("%u",CRC32($key)); $nodeKey=$this-_findservernode (); //If you go beyond the ring, use the dichotomy to find the nearest one, and then the head and tail of the ring to determine the closest node if($this->_keynode >End($this-_nodedata)) { $this->_keynode-=End($this-_nodedata); $nodeKey 2=$this-_findservernode (); if(ABS($nodeKey 2-$this->_keynode) <ABS($nodeKey-$this->_keynode))$nodeKey=$nodeKey 2; } List($config,$num) =Explode(‘_‘,$this->_node[$nodeKey]); if(!$config)Throw New Exception(' Cache config Error '); if(!isset($this->_memcache[$config])) { $this->_memcache[$config] =NewMemcache; List($host,$port) =Explode(‘:‘,$config); $this->_memcache[$config]->connect ($host,$port); } return $this->_memcache[$config]; } /** * Using dichotomy to find the nearest node from the virtual memcache node * @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 functionSet$key,$value,$expire= 0) { return $this->_connectmemcache ($key)->set ($key, Json_encode ($value), 0,$expire); } //to re-add Public functionAdd$key,$value,$expire= 0) { return $this->_connectmemcache ($key)->add ($key, Json_encode ($value), 0,$expire); } Public functionGet$key) { returnJson_decode ($this->_connectmemcache ($key)->get ($key),true); } Public functionDelete$key) { return $this->_connectmemcache ($key)->delete ($key); } }$runData[' begin_time '] =Microtime(true);//Test 10,000 times set plus get for($i= 0;$i<10000;$i++) { $key=MD5(Mt_rand()); $b= Memcachehash::getinstance ()->set ($key, Time(), 10);}Var_dump(Number_format(Microtime(true) -$runData[' Begin_time '],6));//Test Direct Single Table$runData[' begin_time '] =Microtime(true);$m=NewMemcache;$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));
Summary: More than one storage is slower. Please run it on your own at the exact time.
Memcache distributed Storage "consistent hash" CRC32