Wie verhindert man, dass zwei Personen das letzte Ticket kaufen?
Share

In this article
- 01Warum führt ein Lesen- und dann Schreiben der Ticketanzahl zu Überverkäufen?
- 02Warum eine pessimistische Zeilensperre für die letzten Tickets verwenden?
- 03Wie verhindert eine Redis-Reservierung, dass abgebrochene Checkouts den Bestand blockieren?
- 04Was passiert, wenn der Zahlungs-Webhook zweimal ankommt?
- 05Hält das unter Last stand?
Reduzieren Sie die Ticketanzahl innerhalb einer kurzen Datenbanktransaktion, die eine pessimistische Zeilensperre hält, und reservieren Sie jedes Ticket in Redis mit einer Ablaufzeit (TTL). Der zweite Käufer wartet beim Schreiben wenige Millisekunden hinter dem ersten und sieht dann, dass ausverkauft ist. Abgebrochene Checkouts geben ihre Reservierung automatisch frei, wenn die TTL abläuft.
Warum führt ein Lesen- und dann Schreiben der Ticketanzahl zu Überverkäufen?
Zwei Anfragen können denselben verbleibenden Bestand von einem Ticket lesen, beide bestehen die Prüfung und beide schreiben einen Verkauf. Der Bestand war beim Lesen korrekt, aber beim Schreiben veraltet, sodass ein Ticket doppelt verkauft wird. Jeder Lese- und Schreibvorgang auf gemeinsamen Beständen hat dieses Rennen, es sei denn, das Schreiben wird atomar oder gesperrt ausgeführt.
Ein einfacher optimistischer Retry behebt das Korrektheitsproblem, führt aber zu starker Belastung, sobald bei einem beliebten Event die letzten Tickets von vielen Checkouts gleichzeitig angefragt werden: Jeder unterlegene Käufer muss den gesamten Checkout erneut versuchen, nicht nur das Schreiben.
Warum eine pessimistische Zeilensperre für die letzten Tickets verwenden?
Eine pessimistische Sperre lässt den zweiten Schreiber kurz warten, anstatt blind zu scheitern und neu zu versuchen. Für eine heiße Zeile, die viele Käufer gleichzeitig wollen, sind wenige Millisekunden Wartezeit günstiger als komplette Checkout-Wiederholungen. Die Sperre wird nur für die kurze Transaktion gehalten, die die Ticketanzahl reduziert.
Wie verhindert eine Redis-Reservierung, dass abgebrochene Checkouts den Bestand blockieren?
Wenn ein Käufer den Checkout startet, wird das Ticket in Redis mit einer TTL reserviert. Wenn er bezahlt, wird die Reservierung in einen Verkauf umgewandelt. Verlässt er den Prozess, läuft der Schlüssel ab und das Ticket kehrt automatisch in den Bestand zurück. Niemand kann ein Ticket durch geöffneten Checkout-Tab blockieren und einfach weggehen.
Was passiert, wenn der Zahlungs-Webhook zweimal ankommt?
Nichts Besonderes. Der Webhook-Handler ist idempotent, anhand der Bestell-ID eindeutig, und seine einzige Aufgabe ist es, ein Zahlungsbestätigungsereignis an RabbitMQ zu senden. Eine wiederholte Zustellung findet die Bestellung bereits bearbeitet vor, sodass ein Ticket nie doppelt ausgegeben wird. Ein nachgelagerter Verbraucher erzeugt das Ticket und sendet die Bestätigung.
Das gleiche Muster wird Schritt für Schritt in der Notiz zu idempotenten Webhooks erklärt.
Hält das unter Last stand?
Beim Test auf FindYourVibe blieb der Checkout bei über 300 gleichzeitigen Käufern eines einzelnen Events korrekt, ohne dass ein Ticket überverkauft wurde. Die Designentscheidungen, die das ermöglichten, sind die Zeilensperre bei den letzten Tickets, die Redis-Reservierung mit TTL und der idempotente Webhook, der eine Warteschlange bedient.
Pessimistische Zeilensperre bei den letzten Tickets eines Events
Redis-Reservierung mit TTL, um Überverkäufe zu verhindern
RabbitMQ entkoppelt die Ticketausgabe von der Webhook-Antwort
Idempotenter Zahlungs-Webhook, der auf Bestell-ID basiert
Ursprünglich veröffentlicht unter sakshamjain.codes/blog/stop-two-people-buying-the-last-ticket. Brauchen Sie das umgesetzt? Sehen Sie meine Services auf NexoRush oder schreiben Sie mir eine Nachricht.