<?php//+----------------------------------------------------------------------//| Perfect is shit//+----------------------------------------------------------------------//| PHP implementation: Consistent hash algorithm//+----------------------------------------------------------------------//| Author:alexander <gt199899@gmail.com>//+----------------------------------------------------------------- -----
// | Datetime:2017-01-11 16:01:36//+----------------------------------------------------------------------//| Copyright:perfect is shit//+----------------------------------------------------------------------class
consistenthashing {//Ring//hash-> node Private $_ring = Array ();
All nodes//nodes-> hash public $nodes = Array ();
The virtual node of each node is public $virtual = 64;
/** * Construction * @param array $nodes initialized node list */Public function __construct ($nodes = Array ()) { if (!empty ($nodes)) {foreach ($nodes as $value) {
$this->addnode ($value);
/** * Get ring content * @return Array $this->_ring/Public Function getring () {
return $this->_ring; /** * time33 function * @param string $STR * @return 32-bit positive integer * @author great God/public functio n Time33 ($STR) {//hash (i) = hash (i-1) * + str[i]//$hash = 5381; # # To set the hash to 0, even better than set to 5381 distribution.
。。
$hash = 0; $s = MD5 ($STR);
Compared with other versions, the MD5 encryption $seed = 5;
$len = 32;//After encryption length for ($i = 0; $i < $len; $i + +) {//(hash << 5) + hash equivalent to hash * 33
$hash = sprintf ("%u", $hash *) + ord ($s {$i});
$hash = ($hash * + ord ($s {$i})) & 0x7fffffff;
$hash = ($hash << $seed) + $hash + ord ($s {$i});
return $hash & 0x7fffffff; /** * Add node * @param string $node node name * @return Object $this
*/Public Function AddNode ($node) {if (In_array ($node, Array_keys ($this->nodes))) {
Return for ($i = 1; $i <= $this->virtual; $i + +) {$key = $this->time33 ($node. '-' .
$i);
$this->_ring[$key] = $node;
$this->nodes[$node] = $key;
} ksort ($this->_ring, sort_numeric);
return $this; /** * Gets the hash of the string that is mapped to the node above the ring * @param string $key * @return string $node/Public function
GetNode ($key) {$node = current ($this->_ring);
$hash = $this->time33 ($key);
foreach ($this->_ring as $key => $value) {if ($hash <= $key) {$node = $value;
Break
} return $node;
/** * Gets the key that is mapped to a specific node this method requires manual invocation, and is not recommended for use by the program in a special case * @param string $node * @param string $keyPre * @retuRN Mixed */Public function Getkey ($node, $keyPre = "") {if (!in_array ($node, Array_keys ($this->nodes))
) {return false;
} $result = false;
For ($i =1 $i <=10000; $i + +) {$key = $keyPre. MD5 (RAND (1000, 9999));
if ($this->getnode ($key) = = $node) {$result = true;
Break } return $result?
$key: false;
}} $ch _obj = new consistenthashing ();
$ch _obj->addnode (' node_1 ');
$ch _obj->addnode (' node_2 ');
$ch _obj->addnode (' node_3 ');
$ch _obj->addnode (' node_4 ');
$ch _obj->addnode (' node_5 ');
$ch _obj->addnode (' node_6 '); // +----------------------------------------------------------------------
// | View key map to the node//+----------------------------------------------------------------------$key 1 = "
Asofiwjamfdalksjfkasasdflasfja ";
$key 2 = "JAKSLDFJLASFJSDJFIOAFASLKJFLSADKJFL";
$key 3 = "Asjldflkjasfsdjflkajkldsjfksajdlflajs"; $key 4 = "IowanfasijfMasdnfoas ";
$key 5 = "Pqkisndfhoalnfiewlkl";
$key 6 = "Qjklasjdifoajfalsjflsa";
Echo sprintf ("%-50s Map to Node%s\n", $key 1, $ch _obj->getnode ($key 1));
Echo sprintf ("%-50s Map to Node%s\n", $key 2, $ch _obj->getnode ($key 2));
Echo sprintf ("%-50s Map to Node%s\n", $key 3, $ch _obj->getnode ($key 3));
Echo sprintf ("%-50s Map to Node%s\n", $key 4, $ch _obj->getnode ($key 4));
Echo sprintf ("%-50s Map to Node%s\n", $key 5, $ch _obj->getnode ($key 5));
Echo sprintf ("%-50s Map to Node%s\n", $key 6, $ch _obj->getnode ($key 6)); // +----------------------------------------------------------------------
// | View Ring and node information//+----------------------------------------------------------------------/var_dump ($ch _obj->
Getring ());
Var_dump ($ch _obj->nodes); // +----------------------------------------------------------------------
// | Gets the key//+----------------------------------------------------------------------for a particular node//$key 1 = $ch _obj->getkey (
' Node_1 ', ' pre_ ');
Var_dump ($key 1); // +----------------------------------------------------------------------
// |
Test distribution//+----------------------------------------------------------------------//$keys = Array ();
$rings = Array (); for ($i = 1; $i <= 60000 $i + +) {//$key = SHA1 (rand (1000000,9999999));//$node = $ch _obj->getnode ($key
); $rings [$node] = Isset ($rings [$node])?
+ + $rings [$node]: 1;
}//Var_dump ($rings);