Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der Schritte zur Implementierung eines konsistenten Hash-Algorithmus in PHP

Detaillierte Erläuterung der Schritte zur Implementierung eines konsistenten Hash-Algorithmus in PHP

php中世界最好的语言
php中世界最好的语言Original
2018-05-17 11:55:311557Durchsuche

Dieses Mal werde ich Ihnen die Schritte zum Implementieren des konsistenten Hash-Algorithmus in PHP ausführlich erläutern. Was sind die Vorsichtsmaßnahmen für die Implementierung des konsistenten Hash-Algorithmus in PHP? Schauen Sie mal rein.

Der konsistente Hashing-Algorithmus ist ein häufig verwendeter Algorithmus in verteilten Systemen. Warum sollte dieser Algorithmus verwendet werden? Zum Beispiel: Ein verteiltes Speichersystem muss Daten auf bestimmten Knoten (Servern) speichern, wenn sich die Anzahl der Server nicht ändert, wenn gewöhnlicher Hash verwendet wird und dann die Methode der Erfassung Modulo der Gesamtzahl der Server (z. B. Schlüssel % der Gesamtzahl der Server). Wenn ein Server während des Zeitraums ausfällt oder Server hinzugefügt werden müssen, treten Probleme auf. Nach dem Hashing desselben Schlüssels weicht das Ergebnis modulo der Gesamtzahl der Server vom vorherigen Ergebnis ab, was zum Verlust zuvor gespeicherter Daten führt. Daher wird der Verteilungsalgorithmus „Consistent Hash“ (Consistent Hashing) eingeführt

, um die Daten mithilfe einer Hash-Funktion (z. B. md5, sha1) einem Ring zuzuordnen, wie in gezeigt Die obige Abbildung zeigt, dass beim Speichern von Daten zunächst der Hash-Wert des Schlüssels gemäß dem Hash-Algorithmus berechnet wird, der der Position im Ring entspricht, z. B. k1, der derselben Position wie in der Abbildung entspricht, und dann den Server findet Knoten B im Uhrzeigersinn und dann k1 Speichern Sie es auf Knoten B.

Wenn Knoten B ausgefallen ist, fallen die Daten von B auf Knoten C, wie in der Abbildung unten gezeigt

Auf diese Weise wird dies nur der Fall sein Auswirkungen auf Knoten C haben keinen Einfluss auf die Daten anderer Knoten A und D. Hier entsteht jedoch das Problem, dass der C-Knoten überlastet ist. Da der C-Knoten die Daten des B-Knotens trägt, ist er anfällig für Ausfallzeiten, was zu einer ungleichmäßigen Verteilung führt.

Um dieses Problem zu lösen, wird das Konzept des „virtuellen Knotens“ eingeführt: Stellen Sie sich vor, dass es im oberen Ring viele „virtuelle Knoten“ gibt. Ein realer Serverknoten entspricht mehreren virtuellen Knoten. Wenn Daten gespeichert werden, befinden sie sich entlang des Rings. Wenn Sie den virtuellen Knoten im Uhrzeigersinn des Rings finden, finden Sie den entsprechenden realen Serverknoten. Wie in der Abbildung unten gezeigt

A1, A2, B1, B2, C1, C2, D1 und D2 in der Abbildung sind allesamt virtuelle Knoten, die die Daten laden von A1 und A2. Maschine B lädt die Daten von B1 und B2, und Maschine C lädt die Daten von C1 und C2. Da diese virtuellen Knoten zahlreich und gleichmäßig verteilt sind, verursachen sie kein „Lawinen“-Phänomen.

PHP-Implementierung eines konsistenten Hashing-Algorithmus

Eine Schnittstelle ist unten angegeben

/**
 * 一致性哈希实现接口
 * Interface ConsistentHash
 */
interface ConsistentHash
{
 //将字符串转为hash值
 public function cHash($str);
 //添加一台服务器到服务器列表中
 public function addServer($server);
 //从服务器删除一台服务器
 public function removeServer($server);
 //在当前的服务器列表中找到合适的服务器存放数据
 public function lookup($key);
}
Diese Schnittstelle definiert jeweils 4 Methoden, cHash (Strings in Hash-Werte verarbeiten), addServer (einen Server hinzufügen), removeServer (einen Server entfernen), Lookup (einen Server zum Speichern von Daten finden)

sind unten angegeben. Eine spezifische Implementierung dieser Schnittstelle

/**
 * 具体一致性哈希实现
 * author chenqionghe
 * Class MyConsistentHash
 */
class MyConsistentHash implements ConsistentHash
{
 public $serverList = array(); //服务器列列表
 public $virtualPos = array(); //虚拟节点的位置
 public $virtualPosNum = 5;  //每个节点对应5个虚节点
 /**
  * 将字符串转换成32位无符号整数hash值
  * @param $str
  * @return int
  */
 public function cHash($str)
 {
  $str = md5($str);
  return sprintf('%u', crc32($str));
 }
 /**
  * 在当前的服务器列表中找到合适的服务器存放数据
  * @param $key 键名
  * @return mixed 返回服务器IP地址
  */
 public function lookup($key)
 {
  $point = $this->cHash($key);//落点的hash值
  $finalServer = current($this->virtualPos);//先取圆环上最小的一个节点当成结果
  foreach($this->virtualPos as $pos=>$server)
  {
   if($point <= $pos)
   {
    $finalServer = $server;
    break;
   }
  }
  reset($this->virtualPos);//重置圆环的指针为第一个
  return $finalServer;
 }
 /**
  * 添加一台服务器到服务器列表中
  * @param $server 服务器IP地址
  * @return bool
  */
 public function addServer($server)
 {
  if(!isset($this->serverList[$server]))
  {
   for($i=0; $i<$this->virtualPosNum; $i++)
   {
    $pos = $this->cHash($server . '-' . $i);
    $this->virtualPos[$pos] = $server;
    $this->serverList[$server][] = $pos;
   }
   ksort($this->virtualPos,SORT_NUMERIC);
  }
  return TRUE;
 }
 /**
  * 移除一台服务器(循环所有的虚节点,删除值为该服务器地址的虚节点)
  * @param $key
  * @return bool
  */
 public function removeServer($key)
 {
  if(isset($this->serverList[$key]))
  {
   //删除对应虚节点
   foreach($this->serverList[$key] as $pos)
   {
    unset($this->virtualPos[$pos]);
   }
   //删除对应服务器
   unset($this->serverList[$key]);
  }
  return TRUE;
 }
}

Dann testen wir den Algorithmus

$hashServer = new MyConsistentHash();
$hashServer->addServer('192.168.1.1');
$hashServer->addServer('192.168.1.2');
$hashServer->addServer('192.168.1.3');
$hashServer->addServer('192.168.1.4');
$hashServer->addServer('192.168.1.5');
$hashServer->addServer('192.168.1.6');
$hashServer->addServer('192.168.1.7');
$hashServer->addServer('192.168.1.8');
$hashServer->addServer('192.168.1.9');
$hashServer->addServer('192.168.1.10');
echo "增加十台服务器192.168.1.1~192.168.1.10<br />";
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';
echo "移除一台服务器192.168.1.2<br />";
$hashServer->removeServer('192.168.1.2');
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';
echo "移除一台服务器192.168.1.6<br />";
$hashServer->removeServer('192.168.1.6');
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';
echo "移除一台服务器192.168.1.8<br />";
$hashServer->removeServer('192.168.1.8');
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';
echo "移除一台服务器192.168.1.2<br />";
$hashServer->removeServer('192.168.1.2');
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';
echo "增加一台服务器192.168.1.11<br />";
$hashServer->addServer('192.168.1.11');
echo "保存 key1 到 server :".$hashServer->lookup('key1') . '<br />';
echo "保存 key2 到 server :".$hashServer->lookup('key2') . '<br />';
echo "保存 key3 到 server :".$hashServer->lookup('key3') . '<br />';
echo "保存 key4 到 server :".$hashServer->lookup('key4') . '<br />';
echo "保存 key5 到 server :".$hashServer->lookup('key5') . '<br />';
echo "保存 key6 到 server :".$hashServer->lookup('key6') . '<br />';
echo "保存 key7 到 server :".$hashServer->lookup('key7') . '<br />';
echo "保存 key8 到 server :".$hashServer->lookup('key8') . '<br />';
echo "保存 key9 到 server :".$hashServer->lookup('key9') . '<br />';
echo "保存 key10 到 server :".$hashServer->lookup('key10') . '<br />';
echo '<hr />';

Die laufenden Ergebnisse sind wie folgt

Fügen Sie zehn Server 192.168.1.1~192.168.1.10 hinzu
Speichern Sie Schlüssel1 auf Server:192.168.1.2
Speichern Sie Schlüssel2 auf Server:192.168.1.1
Speichern Sie Schlüssel3 auf Server:192.168.1.6
Schlüssel 4 auf Server speichern: 192.168.1.8
Schlüssel 5 auf Server speichern: 192.168.1.9
Schlüssel 6 auf Server speichern: 192.168.1.10
Schlüssel 7 auf Server speichern: 192.168.1.7
Schlüssel 8 auf dem Server speichern 192.168.1.4 Schlüssel2 auf Server:192.168.1.1
Schlüssel3 auf Server speichern:192.168.1.6
Schlüssel4 auf Server speichern:192.168.1.8
Schlüssel5 auf Server speichern:192.168.1.9
Schlüssel6 auf Server speichern:192.168. 1.10
Schlüssel 7 auf Server speichern: 192.168.1.7
Schlüssel 8 auf Server speichern: 192.168.1.4
Schlüssel 9 auf Server speichern: 192.168.1.7
Schlüssel 10 auf Server speichern: 192.168.1.4
Entfernen Sie a Server 192.168.1.6
Schlüssel 1 auf Server speichern: 192.168.1.7
Schlüssel 2 auf Server speichern: 192.168.1.1
Schlüssel 3 auf Server speichern: 192.168.1.3
Schlüssel 4 auf Server speichern: 192.168.1.8
Schlüssel5 auf Server speichern:192.168.1.9
Schlüssel6 auf Server speichern:192.168.1.10
Schlüssel7 auf Server speichern:192.168.1.7
Schlüssel8 auf Server speichern:192.168.1.4
Schlüssel9 auf Server speichern: 192.168.1.7
Schlüssel 10 auf Server speichern: 192.168.1.4
Server 192.168.1.8 entfernen
Schlüssel 1 auf Server speichern: 192.168.1.7
Schlüssel 2 auf Server speichern: 192.168 .1.1
Schlüssel 3 speichern auf Server: 192.168.1.3
Schlüssel 4 auf Server speichern: 192.168.1.10
Schlüssel 5 auf Server speichern: 192.168.1.9
Schlüssel 6 auf Server speichern: 192.168.1.10
Schlüssel 7 auf Server speichern: 192.168.1.7
Schlüssel 8 auf Server speichern: 192.168.1.4
Schlüssel 9 auf Server speichern: 192.168.1.7
Schlüssel 10 auf Server speichern: 192.168.1.4
Server 192.168.1.2 entfernen
Schlüssel 1 auf Server speichern: 192.168.1.7
Schlüssel2 auf Server speichern:192.168.1.1
Schlüssel3 auf Server speichern:192.168.1.3
Schlüssel4 auf Server speichern:192.168.1.10
Schlüssel5 auf Server speichern:192.168.1.9
Speichern Sie Schlüssel6 auf Server: 192.168.1.10
Speichern Sie Schlüssel7 auf Server:192.168.1.7
Speichern Sie Schlüssel8 auf Server:192.168.1.4
Speichern Sie Schlüssel9 auf Server:192.168.1.7
Speichern Sie Schlüssel10 auf Server:192.168 .1.4
Fügen Sie einen Server 192.168.1.11 hinzu
Speichern Sie Schlüssel1 auf Server:192.168.1.7
Speichern Sie Schlüssel2 auf Server:192.168.1.1
Speichern Sie Schlüssel3 auf Server:192.168.1.11
Speichern Sie Schlüssel4 auf Server:192.168.1.10
Schlüssel5 auf Server speichern:192.168.1.9
Schlüssel6 auf Server speichern:192.168.1.10
Schlüssel7 auf Server speichern:192.168.1.7
Schlüssel8 auf Server speichern:192.168.1.4
Schlüssel 9 auf Server speichern: 192.168.1.7
Schlüssel 10 auf Server speichern: 192.168.1.4


Ja, Sie können sehen, dass konsistentes Hashing verwendet wird. Schließlich unabhängig davon, ob Server hinzugefügt oder reduziert werden Server, die Integrität und Einheitlichkeit der Daten sind weitestgehend gewährleistet.

Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie auf anderen chinesischen PHP-Websites . Verwandte Artikel!

Empfohlene Lektüre:

Detaillierte Erläuterung der Prinzipien und Verwendung der automatischen Befüllung des thinkPHP-Frameworks

Detaillierte Erläuterung der Verwendung von PHP Decorator Modus

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Schritte zur Implementierung eines konsistenten Hash-Algorithmus in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn