GH GambleHub

Təkrarlama strategiyaları və idempotentlik

1) Niyə lazımdır

Şəbəkələrdə nasazlıqlar normadır: taymaut, transient-səhvlər, şəbəkə flappinqləri, həddindən artıq yükləmə. Retrajlar yalnız etibarlılığı artırır:

1. təkrar təhlükəsiz (idempotenten),

2. təkrar arasında saxlanılır,

3. Limitlərə/kvotalara və asılılığın «sağlamlığına» hörmət edilir.

Məqsəd - saxta dubl və yarış olmadan biznes əməliyyatları səviyyəsində effectively-once davranış.

2) Çatdırılma semantikasının taksonomiyası

At-most-once: təkrarsız, itki riski (loging, fire-and-forget).
At-least-once: dublikatlar mümkündür → istehlakçının idempotantlığına ehtiyacı var (əksər növbələr, webhucks).
Effectively-once: dublikatlar mümkündür, lakin düzgün deduplizasiya (açarlar, əməliyyatlar, outbox).

3) Nə zaman retraj və nə zaman deyil

Retraitin mənası var: '408', '429' (riayət edərək 'Retry-After'), '425' (Too Early), '499' (perimetrdə client closed), '5xx', '504', şəbəkə vaxtları/fasilələri, '502' şlüz, 'connection reset ".
Sorğu dəyişdirilmədən geri çəkilmir: '400/ 401/403/404/422'.
Mübahisəli hallar: '409 Conflict' (adətən retraim deyil; əvvəlcə əməliyyatın vəziyyətini oxuyuruq/niyyəti yenidən təsdiqləyirik).

4) Taymaut, backoff və jitter

4. 1 Qaydalar

Əvvəlcə taymaut, sonra retriyalar: hər bir sorğu «deadline» olmalıdır.
Exponential backoff: 'delay _ n = base 2 ^ n', məhdud 'max _ delay'.
Jitter tələb olunur: «axmaq sinxron dalğaları» aradan qaldırmaq üçün bir təsadüf əlavə edin.

4. 2 Jitter şablonları

Full jitter: 'sleep = rand (0, base2 ^ n)' - ən yaxşı ümumi seçimdir.
Decorrelated jitter: 'sleep = min (max_delay, rand (base, sleep_prev3))' - uzun dialoqlar üçün.
Equal jitter: 'sleep = base2 ^ n/2 + rand (0, base2 ^ n/2)' - yumşaq variasiya.

4. 3 Retry-budget

Retrajların payını məhdudlaşdırın:
  • `retry_budget_per_min = max(α success_rps, floor β)`; adətən 'α = 0. 1–0. 2`.
  • Büdcə tükəndikdə - fail-fast/circuit breaker «açıq» keçid.

5) rate limiting və Circuit Breaker ilə qarşılıqlı

'Retry-After', 'RateLimit-Reset' -ə hörmət edin və bunu geri çevrilmə hesab edin.
Yüksək '5xx '/taymautlarda - retrajların tezliyini və ümumi paralelliyi azaltın.

Circuit breaker:
  • Half-open: məhdud sınağa imkan verir.
  • Açıq: Dərhal rədd edir (resurslara qənaət edir).
  • Closed: adi iş.
  • Write əməliyyatlarında 409/503-i aqressiv retrayları çevirməkdən daha aydın bir ipucu ilə geri qaytarmaq daha yaxşıdır.

6) Write əməliyyatlarının idempotentliyi

6. 1 Ümumi fikir

Eyni niyyət → bir nəticə. Əsas idempotentlik açarı və icra qeydlərinin anbarıdır.

6. 2 HTTP müqaviləsi

Müştəri başlıq göndərir:

Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
Server:
  • ilk uğurla yerinə yetirildikdə saxlayır (açar → nəticə, status, bədən hash);
  • təkrar edildikdə əvvəlki cavabı və 'Idempotency-Replay: true' başlığını qaytarır;
  • bədən münaqişə (eyni açar, lakin digər payload) - '409 Conflict'.

6. 3 Saxlama və TTL

Cədvəl/açar dəyəri: 'idempotency _ key', 'request _ hash', 'result', 'status', 'expiry _ at'.
TTL = mümkün təkrarlama və gec çatdırılma pəncərəsi (adətən ödənişlər üçün 24-72 saat).
Indekslər 'idempotency _ key'; yüksək yük üçün - heş şarding.

6. 4 Nümunə sxemi (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. 5 Prosessor saxta kodu

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) «effectively-once» nümunələri

Transactional Outbox: Biznes hadisəsini qeyd etmək və fon releyeri vasitəsilə eyni DB əməliyyatından mesaj göndərmək; istehlakçı idempotentdir.
İstehlakçıda Inbox/Processed-table: dubllara məhəl qoymamaq üçün 'event _ id' saxlayın.
Kafka-da Exactly-once ≠ biznesdə exactly-once: hətta EOS prodüser/konsumer tətbiqi məntiq hələ də idempotent olmalıdır.
Kompensasiya əməliyyatları (Saga): addımlar geri çəkilərsə və yan təsirlərə səbəb olarsa, sistemi dəyişməz vəziyyətə qaytarırıq.

8) Xüsusi hallar: ödənişlər və maliyyə əməliyyatları

Strong idempotency: açar əməliyyatın məntiqinə bağlıdır (məsələn, 'external _ payment _ id').
PSP-də duplikasiya: 'merchant _ reference' → saxlayın, PSP təkrarlandıqda əvvəlki nəticəni qaytaracaq.
«Müştəridən» retraisi: yalnız 'Idempotency-Key' zamanı icazə verilir, əks halda ikiqat silinmə riski.
Rəqabət qabiliyyəti: icra müddətində «hesab/alət/müqavilə» bloklanması; təkrarlandıqda 409/423 qaytarın.
Müşahidə: metriklər 'idempo _ replay _ total', 'idempo _ conflict _ total'.

9) Vebhuk və xarici çağırışlar

HMAC imzaları və vaxt pəncərəsi; əvvəlcə yoxlama, sonra emal.
Göndəricinin retrayları: eksponensial backoff + jitter, 'max _ attempts' və DLQ.
İstehlakçı - idempotent: 'event _ id' → cədvəl/in-memory cache; «səliqəli» qaydaya zəmanət verilmir.
Kodlar: 2xx = müvəffəqiyyətlə, 4xx = təkrarlamayın, 5xx/taym = təkrarlayın.

10) Növbələr və fon tapşırıqları

At-least-once default → təkrarları qaçılmazdır.
'task _ id '/' event _ id' və icra statusunu saxlayın; dubli - qısa yol «replay».
DLQ və poison-messages: cəhd sayğacı, karantin, əl təhlili.
Rəqabət limitləri (semaforlar) və idempotent işçilər.

11) Version və «təbii» açarları

Natural açarlar (hesab nömrəsi + tarix + sənəd nömrəsi) təkrarlara davamlılığı artırır.
Sxem/versiyanı dəyişdirərkən, 'Idempotency-Key' və ya hash sorğusuna versiya açarını daxil edin.

12) HTTP başlıqları və müştəri ipuçları

'Idempotency-Key', 'Idempotency-Replay', 'Retry-After', 'Prefer: wait = <sec>' (uzun əməliyyatlarda), 'If-Match '/' ETag' (optimist bloklar).
409 «Retry-After» valid ilə 425/429/503 açar toqquşması zamanı.
«Uzun» əməliyyatlar üçün - asinxron statusun qəbulu (status resursuna '202 Accepted' + 'Location').

13) Test və xaos ssenariləri

Negative testləri: ikiqat göndərmə, başqa bir bədən ilə təkrarlama, rasinkron saat.
Qaydanın pozulması: 't2' 't1' -dən əvvəl gəlir.
Enjeksiyon vaxtı/' RST '/' EOF ', yarım sorğular (slow-POST).
Düşmüş idempotency saxlama → davranış fail-closed (ikiqat silinməkdən daha yaxşı imtina).

14) Metriklər və alertlər

`retries_total{reason}`, `retry_budget_used{route}`, `backoff_seconds_bucket`.
`idempo_replay_total`, `idempo_conflict_total`, `duplicate_detected_total`.
Marşrutlar üzrə 409/425/429/5xx payı; p95/p99 retras ilə «uğur üçün vaxt».
Alertlər: retrajın burn-rate büdcəsi, idempotentlik münaqişələrinin artması, DLQ artımı.

15) Antipattern

Bütün səhvləri geri çəkin.
Jitter yoxluğu → sinxron retraj dalğaları.
TTL və təmizləmə olmadan uzun ömürlü açarlar.
Yan təsir kommit sonra nəticəni saxlamaq (outbox pozulması).
'trace _ id '/' idempotency _ key' → olmadan forensika mümkün deyil.
Write əməliyyatlarında aqressiv paralel retralar.

16) Prod hazırlıq yoxlama siyahısı

  • Vahid siyasət: nə retraim, nə yoxdur; kodlar və müştəri ipuçları.
  • Eksponensial backoff + full jitter; 'retry _ budget' tərəfindən verilmişdir.
  • 'Idempotency-Key' müqaviləsi + TTL ilə nəticələrin saxlanması.
  • Hadisələr üçün Outbox/Inbox; DLQ; rəqabət limitləri.
  • circuit breaker ilə inteqrasiya, respect 'Retry-After'.
  • Retralar/dublikatlar/münaqişələr üzrə metriklər/alertlər.
  • Xaos testləri və şəbəkə uğursuzluqlarının emulyasiyası.
  • Müştərilər üçün sənədləşmə: backoff nümunələri və statuslar.

17) TL; DR

Retrajlar yalnız idempotentlik ilə birlikdə faydalıdır. 'Idempotency-Key' daxil edin və nəticələr saxlayın, jitter və retry-budget ilə eksponensial backoff tətbiq edin, 'Retry-After' hörmət edin, circuit breaker ilə inteqrasiya edin. Hadisələr üçün - outbox/inbox; ödənişlər üçün - ciddi dekuplikasiya və bloklama. Retrajları və münaqişələri ölçün, təkrarları və vaxtları sınayın.

Contact

Bizimlə əlaqə

Hər hansı sualınız və ya dəstək ehtiyacınız varsa — bizimlə əlaqə saxlayın.Həmişə köməyə hazırıq!

Telegram
@Gamble_GC
İnteqrasiyaya başla

Email — məcburidir. Telegram və ya WhatsApp — istəyə bağlıdır.

Adınız istəyə bağlı
Email istəyə bağlı
Mövzu istəyə bağlı
Mesaj istəyə bağlı
Telegram istəyə bağlı
@
Əgər Telegram daxil etsəniz — Email ilə yanaşı orada da cavab verəcəyik.
WhatsApp istəyə bağlı
Format: ölkə kodu + nömrə (məsələn, +994XXXXXXXXX).

Düyməyə basmaqla məlumatların işlənməsinə razılıq vermiş olursunuz.