GH GambleHub

Strategie powtarzania i idempotencja

1) Dlaczego go potrzebujesz

W sieciach awarie są normą: timeouts, przejściowe błędy, klapki sieciowe, przeciążenie. Rekolekcje poprawiają niezawodność tylko wtedy, gdy:

1. powtarzać bezpieczne (idempotent),

2. obserwuje się opóźnienia między powtórzeniami,

3. przestrzegane są limity/kwoty i uzależnienia „zdrowie”.

Celem jest skuteczne zachowanie raz na poziomie operacji biznesowych bez fałszywych zabiegów i wyścigów.

2) Taksonomia semantyki dostawy

Najwyższy czas: brak powtarzania, ryzyko utraty (wyrębu, pożaru i zapomnienia).
Przynajmniej raz: możliwe są duplikaty → potrzebna jest idempotencja konsumentów (większość kolejek, haków internetowych).
Effectively-once: duplikaty są możliwe, ale deduplicated poprawnie (klucze, transakcje, outbox).

3) Kiedy wycofać i kiedy nie

Odwrót ma sens: '408', '429' (obserwując 'Retry-After'), '425' (Too Early), '499' (klient zamknięty na obwodzie), '5xx', '504', czasy/przerwy sieciowe, '502' na bramce, 'reset połączenia'.
Nie wycofuj się bez zmiany zapytania: '400/ 401/403/404/422'.
Kontrowersyjne przypadki: „409 konflikt” (zwykle nie retrayim; najpierw odczytujemy stan operacji/potwierdzamy zamiar).

4) Timeouts, backoff i jitter

4. 1 Zasady

Najpierw czas, potem retro: każdy wniosek musi mieć „termin”.
Wykładniczy backoff: 'delay _ n = base 2 ^ n', limit' max _ delay '.
Jitter jest wymagany: dodać losowość decouple „nudne fale synchroniczne”.

4. 2 wzory Jittera

Full jitter: 'sleep = rand (0, base2 ^ n)' to najlepszy wybór ogólny.
Udekorowany jitter: 'sleep = min (max_delay, rand (base, sleep_prev3))' - dla długich dialogów.
Równy jitter: 'sen = base2 ^ n/2 + rand (0, base2 ^ n/2)' - odmiana miękka.

4. 3 Retry-budget

Ograniczyć odsetek przekładni:
  • „retry _ budget _ per _ min = max (α success_rps, floor β)”; zwykle 'α = 0. 1–0. 2`.
  • Jeśli budżet jest wyczerpany, przełączyć na awaryjny szybki/wyłącznik „otwarty”.

5) Interakcja z ograniczaniem prędkości i wyłącznikiem

Szanuj 'Retry-After', 'Limit-Reset' i zliczaj go w cofnięciu.
Przy wysokim '5xx '/timeouts - obniżyć częstotliwość retray i ogólną równoczesność.

Wyłącznik:
  • Półotwarte: Pozwala na ograniczone pobieranie próbek.
  • Otwórz: natychmiast odrzuca (zapisuje zasób).
  • Zamknięte: zwykła praca.
  • W przypadku operacji pisania, lepiej jest zwrócić 409/503 z wyraźną wskazówką niż przekręty agresywnych retras.

6) Idempotencja operacji pisania

6. 1 Koncepcja ogólna

Te same intencje → jeden wynik. Podstawą jest klucz idempotencji i przechowywanie zapisów wykonania.

6. 2 Umowa HTTP

Klient wysyła nagłówek:

Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
Serwer:
  • Zapisy (klucz, wynik → status, hash ciała) na pierwszy sukces
  • w przypadku powtórzenia zwraca starą odpowiedź i nagłówek 'Idempotence-Replay: true';
  • w przypadku konfliktu ciała (ten sam klucz, ale inny ładunek) - „409 konflikt”.

6. 3 Przechowywanie i TTL

Klucz tabeli/wartości: 'idempotence _ key', 'request _ hash', 'result', 'status', 'expiry _ at'.
TTL = okno możliwych powtórzeń i późnych dostaw (zwykle 24-72 godziny na płatności).
Indeksy według 'idempotence _ key'; dla wysokiego obciążenia - shading hash.

6. 4 Przykładowy schemat (SQL)

sql
CREATE TABLE idempo_store (
key UUID PRIMARY KEY,
req_hash BYTEA NOT NULL,
status INT NOT NULL,
response JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
expiry_at TIMESTAMPTZ NOT NULL
);

6. Pseudokod 5 Handlera

pseudo handle_write(req):
k = req. headers["Idempotency-Key"]
h = hash(req. body)
rec = idempo_store. get(k)

if rec and rec. req_hash == h:
return rec. status, rec. response, {"Idempotency-Replay": "true"}

if rec and rec. req_hash!= h:
return 409, problem("IDEMPOTENT_CONFLICT")

begin tx result = apply_business_mutation (req) # change status upsert once (idempo_store, key = k, req_hash=h, status = 201, response = result, expiry = now () + 2d)
commit

return 201, result

7) wzory „skutecznie raz”

Transactional Outbox: nagrywanie zdarzenia biznesowego i wysyłanie wiadomości z tej samej transakcji w bazie danych przez przekaźnik tła; konsument jest idempotentem.
Skrzynka odbiorcza/tabela przetworzona u konsumenta: zapisz 'event _ id', aby zignorować duplikaty.
Dokładnie raz na Kafce "dokładnie raz w biznesie: nawet z producentem/konsumentem EOS, zastosowana logika nadal powinna być idempotentna.
Transakcje kompensacyjne (Saga): jeśli kroki wycofują się i powodują skutki uboczne, zwracamy system do niezmiennego.

8) Przypadki specjalne: płatności i transakcje finansowe

Silna idempotencja: klucz jest związany z logiką operacji (np. "external _ payment _ id').
Deduplication on PSP - Store 'merchant _ reference' → Jeśli zostanie powtórzone, PSP zwróci ten sam wynik.
Przekłady „od klienta”: zezwalają tylko wtedy, gdy 'Idempotence-Key', w przeciwnym razie ryzyko podwójnego odpisu.
Konkurencja: zamki „na rachunek/narzędzie/kontrakt” na czas realizacji; po powtórzeniu, powrót 409/423.
Obserwowalność: metryki 'idempo _ replay _ total', 'idempo _ conflict _ total'.

9) Haki internetowe i wyzwania zewnętrzne

podpisy HMAC i okno czasowe; najpierw weryfikacja, a następnie przetwarzanie.
Przekładki nadawcy: wykładnicze backoff + jitter, 'max _ attempts' i DLQ.
Konsument - idempotent: 'event _ id' → table/in-memory cache; Porządek „porządny” nie jest gwarantowany.
Kody: 2xx = udany, 4xx = nie powtarzaj, 5xx/timeout = powtórz.

10) Kolejki i zadania podstawowe

Co najmniej raz domyślnie → duplikaty są nieuniknione.
Zapisz 'task _ id'/' event _ id' i status wykonania; z duplikatami - krótka ścieżka „replay”.
DLQ i trucizny: próba licznika, kwarantanna, ręczne parsowanie.
Limity konkurencji (semafory) i pracowników idempotentnych.

11) Wersioning i „naturalne” klucze

Klucze naturalne (numer konta + data + numer dokumentu) zwiększają odporność na powtarzanie.
Przy zmianie schematu/wersji należy umieścić klucz wersji w 'Idempotence-Key' lub w hashu zapytania.

12) nagłówki HTTP i linki do klienta

'Idempotency-Key', 'Idempotence-Replay', 'Retry-After', 'Preferer: wait = <sec>' (na długich operacjach), 'If-Match '/' ETag' (blokady optymistyczne).
409 dla kluczowego konfliktu 425/429/503 z ważnym 'Retry-After'.
Dla operacji „długich” - odbiór statusu asynchronicznego ('202 Accepted' + 'Location' na zasób stanu).

13) Scenariusze testowania i chaosu

Testy negatywne: podwójne wysyłanie, powtarzanie z innym ciałem, desynchronizacja zegara.
Brak zamówienia: 't2' jest przed 't1'.
Wtrysk czasu/' RST '/' EOF ', połowa wniosków (slow-POST).
Upadła magazyn idempotencji → nieudane zachowanie (lepsza awaria niż podwójne odpisanie).

14) Mierniki i wpisy

'retries _ total {reason}', 'retry _ budget _ used {route}', 'backoff _ seconds _ bucket'.
'idempo _ replay _ total', 'idempo _ conflict _ total', 'duplikat _ detected _ total'.
Udostępnianie 409/425/429/5xx na trasach; p95/p99 „czas do sukcesu” z rekolekcjami.
Alerty: budżet przekaźnika spalin, gwałtowny wzrost konfliktów idempotencji, wzrost DLQ.

15) Antypattery

Wycofać wszystkie błędy z rzędu.
Brak jitter → synchroniczne fale retras.
Długotrwałe klucze bez TTL i czyszczenia.
Zapisanie wyniku po popełnieniu efektu ubocznego (naruszenie skrzynki zewnętrznej).
Dzienniki bez 'trace _ id'/' idempotence _ key' są → niemożliwe do wygenerowania.
Agresywny równoległy przekaz operacji pisania.

16) Lista kontrolna gotowości Prod

  • Ujednolicona polityka: co retrayim, co nie; kody i instrukcje klienta.
  • Wykładnicze backoff + full jitter; „retry _ budget” określone.
  • Kontrakt „Idempotency-Key” + wyniki przechowywania z TTL.
  • Skrzynka odbiorcza/skrzynka odbiorcza dla wydarzeń; DLQ; ograniczenia konkurencyjne.
  • Integracja z wyłącznikiem, szacunek „Retry-After”.
  • Metrics/Alerts by Retray/Duplikat/Conflict.
  • Zestaw testów chaosu i emulacji awarii sieci.
  • Dokumentacja klienta - przykłady kopii zapasowych i statusów.

17) TL; DR

Rekolekcje są przydatne tylko wraz z idempotencją. Wprowadź 'Idempotence-Key' i przechowywanie wyników, zastosuj wykładnicze backoff z jitter i retry-budget, przestrzegaj 'Retry-After', zintegruj z wyłącznikiem. Dla zdarzeń - skrzynka odbiorcza/skrzynka odbiorcza; w przypadku płatności, ścisłej deduplikacji i zamków. Pomiar przekładów i konfliktów, duplikaty testów i timeouts.

Contact

Skontaktuj się z nami

Napisz do nas w każdej sprawie — pytania, wsparcie, konsultacje.Zawsze jesteśmy gotowi pomóc!

Telegram
@Gamble_GC
Rozpocznij integrację

Email jest wymagany. Telegram lub WhatsApp są opcjonalne.

Twoje imię opcjonalne
Email opcjonalne
Temat opcjonalne
Wiadomość opcjonalne
Telegram opcjonalne
@
Jeśli podasz Telegram — odpowiemy także tam, oprócz emaila.
WhatsApp opcjonalne
Format: kod kraju i numer (np. +48XXXXXXXXX).

Klikając przycisk, wyrażasz zgodę na przetwarzanie swoich danych.