Jak zapobiec sytuacji, że dwie osoby kupią ostatni bilet?
Share

In this article
- 01Dlaczego odczyt, a potem zapis liczby biletów prowadzi do sprzedaży ponad limit?
- 02Dlaczego stosować pesymistyczną blokadę wiersza dla ostatnich biletów?
- 03Jak rezerwacja w Redis z TTL zapobiega blokowaniu zasobów przez porzucone koszyki?
- 04Co się dzieje, gdy webhook płatności przychodzi dwukrotnie?
- 05Czy to działa pod obciążeniem?
Zmniejsz liczbę dostępnych biletów w krótkiej transakcji bazodanowej, która utrzymuje pesymistyczną blokadę wiersza, oraz rezerwuj każdy bilet w Redis z czasem życia (TTL). Drugi kupujący czeka kilka milisekund na zapis, a następnie widzi, że bilety się wyprzedały. Porzucone koszyki automatycznie zwalniają rezerwację po wygaśnięciu TTL.
Dlaczego odczyt, a potem zapis liczby biletów prowadzi do sprzedaży ponad limit?
Dwa żądania mogą odczytać tę samą pozostałą liczbę jednego biletu, oba przechodzą kontrolę i oba zapisują sprzedaż. Liczba była poprawna podczas odczytu, ale nieaktualna podczas zapisu, więc jeden bilet zostaje sprzedany dwukrotnie. Każda operacja odczytu i zapisu na wspólnym zasobie ma ten problem wyścigu, chyba że zapis jest atomowy lub zablokowany.
Proste ponawianie operacji optymistycznej rozwiązuje problem poprawności, ale powoduje przeciążenie, gdy ostatnie bilety na popularne wydarzenie są masowo kupowane: każdy przegrany klient musi powtarzać cały proces zakupu, nie tylko zapis.
Dlaczego stosować pesymistyczną blokadę wiersza dla ostatnich biletów?
Blokada pesymistyczna powoduje, że drugi zapisujący czeka krótko zamiast natychmiastowego błędu i ponawiania bez informacji. Dla jednego gorącego wiersza, na który wielu kupujących chce się rzucić jednocześnie, kilka milisekund oczekiwania jest tańsze niż powtarzanie całego zakupu. Blokada jest utrzymywana tylko podczas krótkiej transakcji zmniejszającej liczbę biletów.
Jak rezerwacja w Redis z TTL zapobiega blokowaniu zasobów przez porzucone koszyki?
Gdy kupujący rozpoczyna zakup, rezerwuj bilet w Redis z czasem życia (TTL). Jeśli zapłaci, rezerwacja zamienia się w sprzedaż. Jeśli odejdzie, klucz wygasa i bilet automatycznie wraca do zasobów. Nikt nie może zablokować biletu, otwierając kartę zakupu i odchodząc.
Co się dzieje, gdy webhook płatności przychodzi dwukrotnie?
Nic specjalnego. Obsługa webhooka jest idempotentna, oparta na ID zamówienia, a jej jedynym zadaniem jest opublikowanie zdarzenia potwierdzenia płatności do RabbitMQ. Powtórna dostawa znajduje zamówienie już obsłużone, więc bilet nigdy nie jest wydany dwukrotnie. Konsument downstream generuje bilet i wysyła potwierdzenie.
Ten sam wzorzec jest szczegółowo opisany w notatce o idempotentnych webhookach.
Czy to działa pod obciążeniem?
W testach na FindYourVibe proces zakupu pozostał poprawny przy ponad 300 jednoczesnych kupujących na jedno wydarzenie, bez sprzedaży ponad limit. Kluczowe elementy to blokada wiersza na ostatnich biletach, rezerwacja w Redis z TTL oraz idempotentny webhook z kolejką.
Pesymistyczna blokada wiersza na ostatnich biletach wydarzenia
Rezerwacja w Redis z TTL, zapobiegająca sprzedaży ponad limit
RabbitMQ oddziela wydawanie biletów od odpowiedzi webhooka
Idempotentny webhook płatności oparty na ID zamówienia
Artykuł pierwotnie opublikowany na sakshamjain.codes/blog/stop-two-people-buying-the-last-ticket. Potrzebujesz takiego rozwiązania? Zobacz moje usługi na NexoRush lub napisz do mnie.