Takrorlar strategiyasi va idempotentlik
1) Nima uchun bu zarur?
Tarmoqlarda nosozliklar - norma: taymautlar, transient-xatolar, tarmoq flappinglari, ortiqcha yuklash. Retrajlar faqat quyidagi hollarda ishonchlilikni oshiradi:1. takrorlash xavfsiz (idempotenten),
2. takrorlash o’rtasidagi chidamlarga rioya qilinadi
3. qaramlik limitlari/kvotalari va «salomatlik» ga hurmat qilinadi.
Maqsad - soxta dubl va poygalarsiz biznes operatsiyalari darajasida effectively-once xulq-atvoridir.
2) Yetkazib berish semantikasining taksonomiyasi
At-most-once: takrorlamasdan, yo’qotish xavfi (loging, fire-and-forget).
At-least-once: dublikatlar bo’lishi mumkin → iste’molchining idempotentligi kerak (aksariyat navbatlar, vebxuklar).
Effectively-once: dublikatlar mumkin, lekin to’g’ri deduplisatsiya qilinadi (kalitlar, tranzaksiyalar, outbox).
3) Qachon retraj qilish, qachon retraj qilish
Retrayt ma’nosi bor:’408’,’429’(’Retry-After’ga rioya qilgan holda),’425’(Too Early),’499’(perimetrda client closed),’5xx’,’504’, tarmoq taymautlari/bo’shliqlari,’502’shlyuzda, «connection reset».
’400/ 401/403/404/422’ soʻrovini oʻzgartirib boʻlmaydi.
Bahsli keyslar:’409 Conflict’(odatda retraim emas; avval operatsiyaning holatini o’qiymiz/niyatni qayta tasdiqlaymiz).
4) Taymautlar, backoff va jitter
4. 1 Qoidalar
Avval taymaut, so’ngra retriyalar: har bir so’rovda «deadline» bo’lishi kerak.
Exponential backoff:’delay _ n = base 2 ^ n’, chegaralanmoqda’max _ delay’.
Jitter majburiy: «ahmoqona sinxron to’lqinlar» ni hal qilish uchun tasodifni qo’shing.
4. 2 Jitter namunalari
Full jitter:’sleep = rand (0, base2 ^ n)’- eng yaxshi umumiy tanlov.
Decorrelated jitter:’sleep = min (max_delay, rand (base, sleep_prev3))’- uzoq dialoglar uchun.
Equal jitter:’sleep = base2 ^ n/2 + rand (0, base2 ^ n/2)’- yumshoq variatsiya.
4. 3 Retry-budget
Retrains ulushini cheklang:- `retry_budget_per_min = max(α success_rps, floor β)`; Odatda’α = 0. 1–0. 2`.
- Agar byudjet tugasa, fail-fast/circuit breaker «open» ga oʻtamiz.
5) rate limiting va Circuit Breaker bilan o’zaro hamkorlik
’Retry-After’,’RateLimit-Reset’ni hurmat qiling va buni bek-off deb hisoblang.
Yuqori’5xx ’/taymautlarda - retraylarning chastotasini va umumiy parallellikni pasaytiring.
- Half-open: cheklangan namunaga ruxsat beradi.
- Open: darhol rad etadi (resursni tejaydi).
- Closed: oddiy ish.
- Write-operatsiyalarda 409/503 ni agressiv retrajlarni aylantirishdan ko’ra aniq ma’lumot bilan qaytarish afzalroqdir.
6) Write-operatsiyalarning idempotentligi
6. 1 Umumiy g’oya
Bir xil niyat → bitta natija. Asosi - idempotentlik kaliti va ijro yozuvlari ombori.
6. 2 HTTP-kontrakt
Mijoz quyidagi sarlavhani yuboradi:
Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
Server:
- birinchi muvaffaqiyatli bajarilganda saqlaydi (kalit → natija, maqom, tana xeshi);
- takrorlanganda, oldingi javobni va’Idempotency-Replay: true’sarlavhasini qaytaradi;
- tana to’qnashuvida (xuddi shu kalit, lekin boshqa payload) -’409 Conflict’.
6. 3 Saqlash va TTL
Jadval/kalit qiymati:’idempotency _ key’,’request _ hash’,’result’,’status’,’expiry _ at’.
TTL = mumkin bo’lgan takrorlash va kechroq yetkazib berish oynasi (odatda to’lovlar uchun 24-72 soat).
’idempotency _ key’ bo’yicha indekslar; yuqori yuklama uchun - xesh bo’yicha chardlash.
6. 4 Sxema misoli (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 Qayta ishlovchining soxta hujjati
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» patternlari
Transactional Outbox: biznes voqeani yozib olish va fon releyeri orqali xuddi shu DB-tranzaksiyadan xabar yuborish; iste’molchi idempotenten.
Inbox/Processed-table isteʼmolchida: dubllarni eʼtiborsiz qoldirish uchun’event _ id’ni saqlaymiz.
Kafka-da exactly-once biznesda ≠ exactly-once: hatto EOS prodyuser/konsumer bilan ham amaliy mantiq baribir idempotent bo’lishi kerak.
Kompensatsiya tranzaksiyalari (Saga): agar qadamlar orqaga qaytsa va nojo’ya ta’sirlarni keltirib chiqarsa, tizimni invariantga qaytaramiz.
8) Xususiy holatlar: to’lovlar va moliyaviy operatsiyalar
Strong idempotency: kalit operatsiya mantig’iga bog’langan (masalan,’external _ payment _ id’).
PSP deduplikatsiyasi:’merchant _ reference’→ ni saqlang.
«Mijozdan» retraisi: faqat’Idempotency-Key’bilan ruxsat berish, aks holda ikki baravar hisobdan chiqarish xavfi.
Raqobatbardoshlik: bajarish vaqtida «akkauntga/vositaga/shartnomaga» blokirovka qilish; takrorlanganda 409/423 raqamini qaytaring.
Kuzatilganlik:’idempo _ replay _ total’,’idempo _ conflict _ total’metrikalari.
9) Vebxuklar va tashqi qo’ng’iroqlar
HMAC imzolari va vaqt oynasi; avval tekshirish, keyin qayta ishlash.
Jo’natuvchining retraisi: eksponensial backoff + jitter,’max _ attempts’va DLQ.
Iste’molchi - idempotent:’event _ id’→ jadval/in-memory cache; «toza» tartib kafolatlanmagan.
Kodlar: 2xx = muvaffaqiyatli, 4xx = takrorlamang, 5xx/taymaut = takrorlamang.
10) Navbatlar va fon vazifalari
At-least-once andoza → dublikatlar muqarrar.
’task _ id ’/’ event _ id’ va bajarish holatini saqlang; dubli bo’lganda - «replay» qisqa yo’li.
DLQ va poison-messages: urinishlar hisoblagichi, karantin, qoʻlda tahlil qilish.
Raqobat limitlari (semaforlar) va idempotent vorkerlar.
11) Versiyalash va «tabiiy» kalitlar
Natural kalitlar (hisob raqami + sana + hujjat raqami) takrorlashga chidamliligini oshiradi.
Sxema/versiyani oʻzgartirayotganda, «Idempotency-Key» yoki soʻrov xeshiga versiya kalitini kiriting.
12) HTTP-sarlavhalar va mijozga maslahatlar
’Idempotency-Key’,’Idempotency-Replay’,’Retry-After’,’Prefer: wait = <sec>’(uzoq operatsiyalarda),’If-Match ’/’ ETag’(optimistik blokirovkalar).
409 «Retry-After» valid bilan 425/429/503 kalit to’qnashganda.
«Uzoq» operatsiyalar uchun - asinxron maqomni qabul qilish (maqom resursiga’202 Accepted’+’Location’).
13) Test va xaos-stsenariylar
Negative-testlar: ikki marta jo’natish, boshqa tana bilan takrorlash, soatlarning tarqalishi.
Tartib buzilishi:’t2’erta keladi’t1’.
Taymautlarni in’ektsiya qilish/’ RST ’/’ EOF’, yarim so’rovlar (slow-POST).
Yiqilgan idempotency → xatti-harakati (ikki marta hisobdan chiqarishdan koʻra, rad etish yaxshiroqdir).
14) Metrika va alertlar
`retries_total{reason}`, `retry_budget_used{route}`, `backoff_seconds_bucket`.
`idempo_replay_total`, `idempo_conflict_total`, `duplicate_detected_total`.
Yo’nalishlar bo’yicha 409/425/429/5xx ulushi; retralar bilan p95/p99 «muvaffaqiyatga qadar vaqt».
Alertlar: retraylarning burn-rate byudjeti, idempotentlik to’qnashuvlarining ko’payishi, DLQ o’sishi.
15) Antipatternlar
Xatolarni ketma-ket qaytarish.
Jitter yo’qligi → retraylarning sinxron to’lqinlari.
TTL va tozalanmagan uzoq umr ko’radigan kalitlar.
Nojo’ya ta’sirdan so’ng natijani saqlash (outbox buzilishi).
’trace _ id ’/’ idempotency _ key’ → logisiz forensika mumkin emas.
Write operatsiyalarida tajovuzkor parallel retralar.
16) Prod-tayyorlik chek-varaqasi
- Yagona siyosat: nima retraj, nima yo’q; kodlar va mijozga ko’rsatmalar.
- Eksponensial backoff + full jitter; berilgan’retry _ budget’.
- «Idempotency-Key» kontrakti + TTL bilan natijalarni saqlash.
- Hodisalar uchun Outbox/Inbox; DLQ; raqobatbardoshlik limitlari.
- Circuit breaker, respect’Retry-After’bilan integratsiya qilish.
- Retralar/dublikatlar/mojarolar bo’yicha metriklar/alertlar.
- Xaos-testlar to’plami va tarmoq uzilishlarini emulyatsiya qilish.
- Mijozlar uchun hujjatlar: arka-off namunalari va maqomi.
17) TL; DR
Retrajlar faqat idempotentlik bilan birga foydalidir. ’Idempotency-Key’ va natijalar omborini kiriting, jitter va retry-budget bilan eksponensial backoff qo’llang,’Retry-After’ni hurmat qiling, circuit breaker bilan integratsiyalashing. Hodisalar uchun - outbox/inbox; to’lovlar uchun - qat’iy dekuplikatsiya va blokirovka. Retraj va ziddiyatlarni o’lchang, dublikat va taymautlarni sinab ko’ring.