menuTicketing

Wie es funktioniert


Erwerb und Freigabe des Locks

Erwirbt ein Client einen Schlüssel (A), antwortet der Server mit einem von drei möglichen Ergebnissen.

SchlüsselzustandServeraktionAntwort
Nicht registriertSofortige Registrierung (Ablauf = now + lease), Token wird ausgestelltA + token + key
Registriert + Ablauf überschrittenErneuerung (now + lease), neues Token wird ausgestelltA + token + key
Registriert + gültig (belegt)Eintrag in die Warteschlange, Antwort wird zurückgehaltenbei Freigabe/Ablauf A, bei Überschreiten von wait T
  • Die Freigabe wird fair nach FIFO abgearbeitet. Gibt der Halter frei (R), wird der Lock direkt an den vordersten Wartenden übergeben — ohne erneuten Wettlauf, sofort mit neuem Token.
  • lease ist ein Sicherheitsnetz. Stirbt der Client oder vergisst er die Freigabe, kann der Server nach Ablauf der lease-Zeit den Schlüssel automatisch zurückholen und an den nächsten Wartenden weitergeben. Unabhängig vom normalen Freigabe-Ablauf sollte lease daher immer großzügig, aber so bemessen sein, dass ein toter Client die Ressource nicht zu lange blockiert.
  • wait ist die Obergrenze für die Wartezeit beim Erwerb. Bei 0 wird unbegrenzt gewartet, andernfalls gibt der Server auf und antwortet mit T (Timeout), wenn innerhalb dieser Zeit (Sekunden) kein Erwerb zustande kam — ohne Grant, sodass kein Lock verloren geht.

Fencing-Token

Das im A-Antwort enthaltene token ist ein für diesen Grant monoton steigendes u64. Bei jedem Erwerb wird ein Wert ausgestellt, der größer ist als jedes vorherige Token. Auch bei einem Failover setzt der neu aktive Knoten bei einem Wert fort, der größer ist als das größte replizierte Token (Übernahme) — dadurch steigt das Token über den gesamten Cluster hinweg kontinuierlich.

Prüft die zu schützende Ressource (Konto, Datei, Bestellung usw.) lediglich, ob "das gerade gehaltene Token größer ist als das zuletzt gesehene", kann ein nach Ablauf der lease verspätet aufgewachter Client mit einem bereits ungültigen, niedrigeren Token abgewiesen werden. Dadurch bleibt die Sicherheit gewahrt, auch wenn der Lock-Server selbst nicht in jedem Moment perfekt konsistent ist.

Verhalten der Clients

Die offiziellen Clients verhalten sich einheitlich wie folgt (sprachspezifische API-Details siehe Bibliotheken).

  • Pro Adresse wird eine dauerhafte Verbindung gehalten und im Hintergrund verwaltet. Wird nur eine Adresse angegeben, hält der Client intern zwei Verbindungen zum selben Knoten, damit ein kurzzeitiger Abbruch einer davon den Dienst nicht unterbricht.
  • Die Verbindung wird per Round-Robin ausgewählt. Getrennte Knoten werden automatisch ausgeschlossen, im Hintergrund wird alle 3 Sekunden ein Wiederverbindungsversuch unternommen.
  • Anfragen werden pipeline-verarbeitet. Die nächste Anfrage kann gesendet werden, ohne auf die Antwort zu warten, und die Antwortreihenfolge muss nicht der Anfragereihenfolge entsprechen — der Client unterscheidet anhand der zurückgesendeten Kombination (op, key), zu welcher Anfrage eine Antwort gehört. Gibt es mehrere Anfragen mit derselben (op, key)-Kombination, werden sie in Sendereihenfolge zugeordnet.
  • Bricht die Verbindung während eines Erwerbsversuchs ab, wird automatisch zur nächsten Verbindung gewechselt. Erst wenn so viele Versuche wie registrierte Verbindungen erfolglos blieben, wird ein Fehler gemeldet.
  • Die Freigabe wird 5 Sekunden lang im 200-ms-Abstand wiederholt — damit der Lock nicht auf dem Server verbleibt, falls die Verbindung ausgerechnet im Moment der Freigabe unterbrochen ist (letztlich holt ihn zwar auch lease zurück, aber so wird er schneller an den nächsten Wartenden weitergegeben).

Cluster — prioritätsbasiert, ohne Ausfallzeit

  • Die Reihenfolge der peers-Liste bestimmt die Beförderungspriorität (das erste Element hat höchste Priorität). Unter den lebenden Knoten wird derjenige mit der höchsten Priorität zum Aktiven, die übrigen werden zu Standbys, die dessen Zustand in Echtzeit repliziert bekommen.
  • Client-Anfragen bearbeitet nur der Aktive. Clients, die sich mit einem Standby verbinden, werden per M zur Adresse des Aktiven verwiesen und wechseln dorthin.
  • Fällt der Aktive aus oder startet neu, wird ein Standby befördert und übernimmt.
  • Bei geordnetem Beenden (Ctrl+C) übergibt der Aktive die Beförderung zuerst an seinen Nachfolger (Handoff) und leitet die Clients dann um, sodass die Lücke ohne Aktiven minimal bleibt.
  • Automatische Rückstufung: Werden durch eine Netzwerkpartition o. Ä. zwei Knoten gleichzeitig aktiv, erkennt der Knoten mit der niedrigeren Priorität den anderen und stuft sich selbst zum Standby zurück (verhindert einen dauerhaften Split-Brain).

Diese Beförderungsmethode basiert nicht auf einem Quorum (Mehrheitsvotum). Deshalb spielt es keine Rolle, ob die Anzahl der Server gerade oder ungerade ist, und solange mindestens ein Knoten lebt, bleibt der Dienst erhalten.

Anzahl ServerAusfallfreiGleichzeitige Ausfälle toleriertAnmerkung
1Am schnellsten. Bei Neustart kurze Unterbrechung
21Minimalkonfiguration für Ausfallfreiheit. In den meisten Fällen ausreichend
32Redundanz bleibt auch während Wartung eines Knotens erhalten
4+N−1Nur höhere Verbreitungskosten — nicht empfohlen

Was zur Konsistenz zu beachten ist

Da die prioritätsbasierte Beförderung kein Konsensverfahren ist, können im Moment einer Netzwerkpartition beide Seiten kurzzeitig gleichzeitig aktiv sein, und aufgrund der asynchronen Replikation können im Moment eines Failovers einzelne Grants verloren gehen. Das heißt: während Failover/Partition ist der gegenseitige Ausschluss nicht zu 100 % garantiert. Wird eine starke Garantie benötigt, sollte die zu schützende Ressource das zuvor beschriebene Fencing-Token prüfen — werden ältere (kleinere) Token abgelehnt, bleibt die Sicherheit auch dann gewahrt, wenn der Lock-Server nicht perfekt konsistent ist.