Heim  >  Artikel  >  PHP-Framework  >  So implementieren Sie verteilte Sperren in Swoole

So implementieren Sie verteilte Sperren in Swoole

PHPz
PHPzOriginal
2023-06-25 16:45:21952Durchsuche

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:

  1. Gegenseitige Exklusivität: Nur ein Prozess oder Thread kann die Sperre gleichzeitig belegen.
  2. Wiedereintritt: derselbe Prozess oder Thread Sie können die Sperre mehrmals beantragen, aber beim Entsperren muss die gleiche Anzahl von Entsperrvorgängen durchgeführt werden.
  3. Deadlock verhindern: Sie müssen beim Erwerb der Sperre eine Ablaufzeit festlegen, um ein endloses Warten aufgrund von Ausnahmen oder anderen Gründen zu vermeiden
  4. Hohe Verfügbarkeit: Probleme wie Knotenausfall und Netzwerkpartition müssen berücksichtigt werden.
  5. Leistung: Es ist notwendig, Funktionen mit hoher Parallelität und geringer Latenz zu erreichen.

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:

  1. Hohe Leistung: Verwendung eines asynchronen, nicht blockierenden E/A-Modells, das die Parallelitätsfähigkeit des Servers erheblich verbessern kann;
  2. Eingebaute Coroutine: Asynchrone Programmierung kann einfach implementiert werden, ohne dass eine manuelle Durchführung erforderlich ist Erstellen Sie Threads oder Prozesse.
  3. Eingebauter HTTP-/WebSocket-Server: Die Entwicklung von Webanwendungen kann problemlos realisiert werden.
  4. Unterstützt die Kapselung von asynchronem MySQL, Redis, ElasticSearch und anderen gängigen Tools.

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.

  1. Implementierung verteilter Sperren auf Basis von Redis

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.

  1. Implementierung verteilter Sperren auf Basis von Zookeeper

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.

Das Folgende ist der spezifische Implementierungscode:

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;
        }
    }
}

Im obigen Code verwendet die Sperrfunktion eine While-Schleife, um den neuesten Knoten mit einer kleineren Seriennummer als seiner eigenen zu überwachen Die Sperre wurde erworben; die Entsperrfunktion verwendet die Löschfunktion, um den aktuellen Knoten zu löschen.

    Zusammenfassung
In diesem Artikel wird erläutert, wie verteilte Sperren in Swoole implementiert werden. Wir stellen zwei gängige Implementierungsmethoden vor, die auf Redis und Zookeeper basieren, und geben den Implementierungscode an. Als wichtiges technisches Mittel zur Gewährleistung der Datenkonsistenz in verteilten Systemen können verteilte Sperren uns dabei helfen, Probleme wie Parallelitätskonflikte und Dateninkonsistenzen zu vermeiden. Bei der Implementierung verteilter Sperren müssen Sie Aspekte wie gegenseitige Ausschließlichkeit, Wiedereintritt, Deadlock-Verhinderung, Hochverfügbarkeit und Leistung berücksichtigen und basierend auf tatsächlichen Anwendungsszenarien unterschiedliche Implementierungsmethoden auswählen.

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!

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