menuTicketing

Was ist Ticketing?


Warum ein verteilter Lock nötig ist

Wenn dieselbe Ressource (Konto, Bestellung, Bestand, Batch-Job usw.) gleichzeitig von mehreren Prozessen oder mehreren Servern angefasst wird, entsteht ein Wettlauf (Race Condition). In eine Sprache eingebaute Mutexe oder Semaphore gelten nur innerhalb eines einzigen Prozesses — sind es mehrere Prozesse oder verteilen sie sich auf mehrere Server, wird ein eigenes Mittel für gegenseitigen Ausschluss über Prozessgrenzen hinweg benötigt.

Ticketing ist genau dafür da: ein Lock-Server samt Client-Sammlung für gegenseitigen Ausschluss über Prozess- und Servergrenzen hinweg. Der Client verbindet sich per TCP mit dem Lock-Server, erwirbt (acquire) einen benannten Schlüssel (Key), durchläuft den kritischen Abschnitt und gibt ihn danach wieder frei (release).

Kernphilosophie

⚡ Leichtgewichtig und schnell

Ticketing verwendet kein JSON, sondern ein Frame-Protokoll aus binären Feldern fester Breite. Nach dem Dispatch anhand von 1 Byte Op werden die für den jeweiligen Op festen Bytes gemäß ihrer Länge gelesen, nur der letzte Key wird bis zum Zeilenumbruch (\n) gelesen. Das Parsen ist eher ein reines Auslesen von Offsets als echtes Parsen und verursacht dadurch weniger Overhead als das Parsen von JSON bei jeder Anfrage.

🔑 Sicherheit über Fencing-Tokens

Bei jedem Erwerb eines Locks liefert der Server zusätzlich ein monoton steigendes u64-Fencing-Token mit. Prüft die zu schützende Ressource die Monotonie dieses Tokens, kann ein nach Ablauf der lease verspätet aufgewachter Client mit einem niedrigeren Token abgewiesen werden. Dadurch bleibt die Sicherheit gewahrt, auch wenn der Lock-Server selbst nicht in jedem Moment perfekt konsistent ist — das ist besonders während eines Failovers wichtig.

🔄 Cluster ohne Ausfallzeit

Ein einzelner Server reicht für den Betrieb (Single-Modus), für unterbrechungsfreien Betrieb wird jedoch ein Cluster aus mindestens 2 Knoten gebildet. Der Cluster wählt nicht per Konsens (Quorum), sondern prioritätsbasiert einen Aktiven, die übrigen werden zu Standbys, die in Echtzeit repliziert bekommen. Stirbt der Aktive (auch bei Neustart) oder beendet er sich geordnet (graceful), übernimmt ein Standby. Details zur Funktionsweise siehe die Seite Funktionsweise.

🌐 Sprachunabhängig

Auf demselben binären Protokoll werden offizielle Clients für 8 Sprachen bereitgestellt: Rust, Java/Kotlin, JavaScript/TypeScript, Python, C#, Go, Ruby, C/C++. Jede Sprache stellt die API auf die für ihr Ökosystem natürliche Weise bereit — zum Beispiel async/await-Sprachen asynchron, Go/Ruby/C blockierend mit Hintergrund-Thread. Das Protokoll ist über alle Sprachen hinweg byte-identisch. Installationsanleitungen und Beispiele je Sprache finden sich auf der Seite Bibliotheken.