This article mainly introduces the Memcache consistency hash PHP implementation method, the example analyzes the memcache in the hash consistency realization principle and the related technique, the need friend may refer to the next
-->
This article illustrates the PHP implementation method of Memcache consistent hash. Share to everyone for your reference. Specifically as follows:
Recently looking at some of the distributed aspects of the article, so the use of PHP to achieve consistency hash to practice practicing, formerly commonly used is the most original hash model to do distributed, when the production process to add or remove a memcache will result in all data failure, consistent hash is to solve this problem, To minimize the failure data, the relevant information can be Google!
PHP to achieve a certain lack of efficiency, if you want to be efficient, or write expansion is better
After testing, 5 memcache, each memcache generated 100 virtual nodes, set plus get1000 times, with a single memcache direct set plus get slow 5 times times, so the efficiency is general, to be optimized!
Before reading this article, it is best to know the binary lookup method.
Implementation process:
Memcache configuration ip+ Port + virtual node serial number to do hash, using the CRC32, forming a closed loop.
CRC32 the key to be manipulated
Binary search for the nearest virtual node in the virtual node ring
Extract real Memcache IP and port from virtual node, make single case connection
The code is as follows:
<?php
Class Memcachehashmap {
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, at the same time set get operation, but also more resources, 10 physical servers, using 200 more reasonable]
Private $_virtualnodenum = 200;
Private Function __construct () {
$config = Array (///five Memcache servers
' 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/Loop Create 200 virtual nodes for each memcache server
}
}
Ksort ($this->_node);//created 1000 virtual nodes sorted from small to large by key name
}
Instantiate the class
static public Function getinstance () {
static $MEMCACHEOBJ = null;
if (!is_object ($MEMCACHEOBJ)) {
$MEMCACHEOBJ = new self ();
}
return $MEMCACHEOBJ;
}
Find the location of the corresponding virtual node based on the key that came in
Private Function _connectmemcache ($key) {
$this->_nodedata = Array_keys ($this->_node);//array of keys for all virtual nodes
$this->_keynode = sprintf ("%u", CRC32 ($key));//Calculate the hash value of the key
$nodeKey = $this->_findservernode ()//find the corresponding virtual node
If you exceed the ring, look for a nearest and then the loop's head and tail to make a judgment, take the nearest 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;
}
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];
}
The binary method finds the nearest virtual node location based on the given value
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);
Test 10,000 times set plus get
For ($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)];
?>
I hope this article will help you with your PHP program design.