PHP Implementation Consistency HASH Algorithm Example

  • 2021-09-12 00:42:37
  • OfStack

In this paper, an example is given to describe the 1-dimensional HASH algorithm implemented by PHP. Share it for your reference, as follows:


<?php
// +----------------------------------------------------------------------
// | Perfect Is Shit
// +----------------------------------------------------------------------
// | PHP Achieve: 1 Pathogenic 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 
  //  Node  -> hash
  public $nodes = array();
  //  Virtual nodes for each node 
  public $virtual = 64;
  /**
   *  Structure 
   * @param array $nodes  Initialized node list 
   */
  public function __construct($nodes = array())
  {
    if (!empty($nodes)) {
      foreach ($nodes as $value) {
        $this->addNode($value);
      }
    }
  }
  /**
   *  Get the contents of the ring 
   * @return array $this->_ring
   */
  public function getRing()
  {
    return $this->_ring;
  }
  /**
   * time33  Function 
   * @param string $str
   * @return 32 Positive bit integer 
   * @author  Great gods 
   */
  public function time33($str)
  {
    // hash(i) = hash(i-1) * 33 + str[i]
    // $hash = 5381; ##  Will hash Set to 0 Compared with setting to 5381 The distribution effect is better! ! ! 
    $hash = 0;
    $s  = md5($str); // Compared with other versions, the md5 Encryption 
    $seed = 5;
    $len = 32;// Encrypted length 32
    for ($i = 0; $i < $len; $i++) {
      // (hash << 5) + hash  Equivalent to  hash * 33
      //$hash = sprintf("%u", $hash * 33) + ord($s{$i});
      //$hash = ($hash * 33 + ord($s{$i})) & 0x7FFFFFFF;
      $hash = ($hash << $seed) + $hash + ord($s{$i});
    }
    return $hash & 0x7FFFFFFF;
  }
  /**
   *  Add nodes 
   * @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;
  }
  /**
   *  Object of the string HASH Nodes mapped to on 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;
  }
  /**
   *  Object mapped to a specific node KEY
   *  This method needs to be called manually, and it is not recommended to use this method in programs without special circumstances 
   * @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 Nodes mapped to 
// +----------------------------------------------------------------------
$key1 = "asofiwjamfdalksjfkasasdflasfja";
$key2 = "jaksldfjlasfjsdjfioafaslkjflsadkjfl";
$key3 = "asjldflkjasfsdjflkajkldsjfksajdlflajs";
$key4 = "iowanfasijfmasdnfoas";
$key5 = "pqkisndfhoalnfiewlkl";
$key6 = "qjklasjdifoajfalsjflsa";
echo sprintf("%-50s  Map to Node  %s\n", $key1, $ch_obj->getNode($key1));
echo sprintf("%-50s  Map to Node  %s\n", $key2, $ch_obj->getNode($key2));
echo sprintf("%-50s  Map to Node  %s\n", $key3, $ch_obj->getNode($key3));
echo sprintf("%-50s  Map to Node  %s\n", $key4, $ch_obj->getNode($key4));
echo sprintf("%-50s  Map to Node  %s\n", $key5, $ch_obj->getNode($key5));
echo sprintf("%-50s  Map to Node  %s\n", $key6, $ch_obj->getNode($key6));
// +----------------------------------------------------------------------
// |  View ring and node information 
// +----------------------------------------------------------------------
// var_dump($ch_obj->getRing());
// var_dump($ch_obj->nodes);
// +----------------------------------------------------------------------
// |  Object for a specific node KEY
// +----------------------------------------------------------------------
// $key1 = $ch_obj->getKey('node_1', 'pre_');
// var_dump($key1);
// +----------------------------------------------------------------------
// |  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);

Run results:


asofiwjamfdalksjfkasasdflasfja            Map to Node  node_1
jaksldfjlasfjsdjfioafaslkjflsadkjfl         Map to Node  node_2
asjldflkjasfsdjflkajkldsjfksajdlflajs        Map to Node  node_1
iowanfasijfmasdnfoas                 Map to Node  node_2
pqkisndfhoalnfiewlkl                 Map to Node  node_3
qjklasjdifoajfalsjflsa                Map to Node  node_5

PS: Here are two online tools related to hash for your reference:

Online hash/hash algorithm encryption tool:
http://tools.ofstack.com/password/hash_encrypt

Online MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160 Encryption Tool:
http://tools.ofstack.com/password/hash_md5_sha

For more readers interested in PHP related contents, please check the special topics of this site: "Summary of php Encryption Methods", "Summary of PHP Encoding and Transcoding Operation Skills", "Summary of PHP Mathematical Operation Skills", "Encyclopedia of PHP Array (Array) Operation Skills", "Summary of php String (string) Usage", "Tutorial of PHP Data Structure and Algorithm", "Summary of php Programming Algorithm" and "Summary of php Regular Expression Usage"

I hope this article is helpful to everyone's PHP programming.


Related articles: