Mit der Entwicklung des Internets und des mobilen Internets sind hohe Parallelität und verteilte Systeme zu unvermeidlichen Problemen in der täglichen Entwicklung geworden. In diesem Fall werden verteilte Sperren zu einem unverzichtbaren Werkzeug, das uns helfen kann, Probleme wie Ressourcenkonkurrenz und Dateninkonsistenz zu vermeiden. In diesem Artikel wird erläutert, wie Sie verteilte Sperren in Swoole implementieren, um Parallelitätsprobleme in verteilten Systemen besser zu lösen.
1. Was ist eine verteilte Sperre?
In einem verteilten System gibt es Situationen, in denen mehrere Prozesse gleichzeitig auf gemeinsam genutzte Ressourcen zugreifen. Um sicherzustellen, dass Daten nicht zerstört werden oder Parallelitätskonflikte auftreten, müssen diese gemeinsam genutzten Ressourcen gesperrt werden. Die verteilte Sperre ist ein Sperrmechanismus, der entwickelt wurde, um die korrekte Nutzung gemeinsam genutzter Ressourcen in einem verteilten System zu erreichen.
Die Implementierung verteilter Sperren ist relativ komplex und im Allgemeinen müssen die folgenden Aspekte berücksichtigt werden:
2. Einführung in Swoole
Swoole ist eine leistungsstarke asynchrone und parallele Netzwerkkommunikations-Engine für die PHP-Sprache. Sie kann den Server und Client verschiedener Protokolle wie TCP/UDP/HTTP/WebSocket implementieren. Zu den Funktionen von Swoole gehören:
Daher weist Swoole eine sehr gute Anpassungsfähigkeit auf und kann zum Aufbau verteilter Systeme mit hoher Parallelität und hoher Leistung verwendet werden.
3. Wie implementiert man verteilte Sperren in Swoole?
Im Folgenden stellen wir vor, wie verteilte Sperren in Swoole implementiert werden.
Redis ist eine speicherbasierte Schlüsselwertdatenbank und eines der am häufigsten verwendeten Tools in verteilten Systemen. Es unterstützt eine Vielzahl von Datenstrukturen, einschließlich Zeichenfolgen, Listen, Mengen, geordneten Mengen usw. Unter anderem kann der Zeichenfolgentyp zum Implementieren verteilter Sperren verwendet werden.
Der allgemeine Prozess der Verwendung von Redis zum Implementieren verteilter Sperren ist wie folgt:
(1) Erhalten Sie ein Redis-Verbindungsobjekt über den Redis-Verbindungspool.
(2) Verwenden Sie den SETNX-Befehl, um einen gegenseitigen Ausschluss der Sperre zu erreichen wenn der Rückgabewert 1 ist, ist die Besetzung erfolgreich.
(3) Um einen Deadlock zu verhindern, legen Sie die Ablaufzeit für die Sperre fest.
(4) Verwenden Sie den DEL-Befehl, um die Sperre aufzuheben.
Das Folgende ist der spezifische Implementierungscode:
class RedisLock { private $redis; public function __construct($config) { $this->redis = new Redis(); $this->redis->connect($config['host'], $config['port'], $config['timeout']); if (!empty($config['auth'])) { $this->redis->auth($config['auth']); } } public function lock($key, $timeout = 10) { $startTime = time(); do { $result = $this->redis->setnx($key, time() + $timeout); if ($result) { return true; } $lockTime = $this->redis->get($key); if ($lockTime && $lockTime < time()) { $oldTime = $this->redis->getset($key, time() + $timeout); if ($oldTime == $lockTime) { return true; } } usleep(100); // 100毫秒等待 } while (time() - $startTime < $timeout); return false; } public function unlock($key) { $this->redis->del($key); } }
Im obigen Code wird in der Sperrfunktion eine Do-While-Schleife verwendet, um auf die Freigabe der Sperre zu warten, wird false zurückgegeben ; DEL wird im Befehl zum Entsperren der Funktion verwendet, um die Sperre aufzuheben. Obwohl diese Methode einfach zu implementieren ist und einen geringen Overhead verursacht, besteht auch eine gewisse Wahrscheinlichkeit eines Deadlocks.
Zookeeper ist ein verteiltes Open-Source-Koordinationssystem, mit dem eine Reihe von Funktionen wie Datensynchronisation und Konfigurationsmanagement in verteilten Systemen implementiert werden können. Der bereitgestellte temporäre sequentielle Knoten (EPHEMERAL_SEQUENTIAL) kann problemlos verteilte Sperren implementieren.
Der allgemeine Prozess zur Verwendung von Zookeeper zum Implementieren verteilter Sperren ist wie folgt:
(1) Erstellen Sie einen Zookeeper-Client und stellen Sie eine Verbindung zum Zookeeper-Server her.
(2) Verwenden Sie die Funktion „createSequential“, um einen temporären sequentiellen Knoten zu erstellen ) Holen Sie sich den Zookeeper. Alle Knoten werden nach der Seriennummer des Knotens sortiert.
(4) Vergleichen Sie die Seriennummer Ihres eigenen Knotens mit der Seriennummer des aktuell kleinsten Knotens. Wenn sie gleich sind, bedeutet dies, dass die Sperre erhalten wurde der neueste Knoten, der kleiner als Ihre eigene Seriennummer ist;
(5) Wenn ein Knoten mit einer kleineren Sequenznummer als seiner eigenen gelöscht wird, erhält der aktuelle Knoten eine Ereignisbenachrichtigung und wiederholt dann Schritt 4.
class ZookeeperLock { private $zk; private $basePath = '/lock'; private $myNode; public function __construct($config) { $this->zk = new Zookeeper(); $this->zk->connect($config['host'] . ':' . $config['port']); if (isset($config['auth'])) { $this->zk->addAuth('digest', $config['auth']); } if (!$this->zk->exists($this->basePath)) { $this->zk->create($this->basePath, null, array(array('perms' => Zookeeper::PERM_ALL, 'scheme' => 'world', 'id' => 'anyone')), null); } } public function lock() { $this->myNode = $this->zk->create($this->basePath . '/node_', null, array(array('perms' => Zookeeper::PERM_ALL, 'scheme' => 'world', 'id' => 'anyone')), Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE); while (true) { $children = $this->zk->getChildren($this->basePath); sort($children); $pos = array_search(basename($this->myNode), $children); if ($pos === 0) { return true; } else { $this->zk->exists($this->basePath . '/' . $children[$pos - 1], function ($event_type, $s, $event_data) { $this->unlock(); }); usleep(100); // 100毫秒等待 } } } public function unlock() { if ($this->myNode) { $this->zk->delete($this->myNode); $this->myNode = null; } } }
Das obige ist der detaillierte Inhalt vonSo implementieren Sie verteilte Sperren in Swoole. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!