GH GambleHub

Exactly-once vs At-least-once

1) Semantikani muhokama qilishning nima keragi bor?

Yetkazib berish semantikasi qabul qiluvchi xato va retrajlarda xabarni qanchalik tez-tez koʻrishini aniqlaydi:
  • At-most-once - takrorlamasdan, lekin yo’qotish mumkin (kamdan-kam hollarda qabul qilinadi).
  • At-least-once - yo’qotmaymiz, lekin dublikatlar bo’lishi mumkin (ko’pgina brokerlar/navbatlarning defolti).
  • Exactly-once - har bir xabar kuzatilgan ta’sir nuqtai nazaridan bir marta qayta ishlanadi.

Asosiy haqiqat: global tranzaksiyalar va sinxron muvofiqliksiz taqsimlangan dunyoda «sof» end-to-end exactly-once erishib bo’lmaydi. Biz exactly-once’ni samarali quramiz: transportda takrorlashga ruxsat beramiz, lekin idempotent bilan ishlov beramiz, shunda kuzatilayotgan ta’sir «xuddi bir marta» bo’ladi.


2) Rad etish modeli va dublikatlar qayerda paydo bo’ladi

Takrorlash quyidagilardan kelib chiqadi:
  • Yo’qotishlar ack/commit (prodyuser/broker/konsumer tasdiqlashni «eshitmadi»).
  • Rahbarlarni/replikalarni qayta saylash, tarmoqdagi uzilishlardan keyin tiklash.
  • Har qanday uchastkada taymautov/retraev (mijoz → broker → konsumer → sink).

Natijada, transportni «yetkazib berishning noyobligiga» tayanib boʻlmaydi. Biz effektlarni boshqaramiz: DBga yozish, pulni hisobdan chiqarish, xat jo’natish va boshqalar.


3) Etkazib beruvchilarda Exactly-once va bu aslida nima

3. 1 Kafka

Gʻishtlarni beradi:
  • Idempotent Producer (`enable. idempotence = true’) - retralarda prodyuser tomonidagi dubllarning oldini oladi.
  • Tranzaksiyalar - bir nechta partiyalar va kommityat iste’mol ofsetlariga («o’tkazib yuborishsiz» read-process-write patterni) atomik ravishda xabarlarni e’lon qiladi.
  • Compaction - oxirgi kalit qiymatini saqlaydi.

Ammo «zanjir oxiri» (sink: BD/to’lov/pochta) baribir idempotentlikni talab qiladi. Aks holda, ishlov beruvchining dubli effekt dublini keltirib chiqaradi.

3. 2 NATS / Rabbit / SQS

Andoza - ack/redelivery bilan at-least-once. Exactly-once dasturlar darajasida erishiladi: kalitlar, dedup-stor, upsert.

Xulosa: Exactly-once transporti ≠ exactly-once effekti. Oxirgisi ishlov beruvchida amalga oshiriladi.


4) At-least-once ustiga samarali exactly-once qurish

4. 1 Idempotent kaliti (idempotency key)

Har bir buyruq/hodisa tabiiy kalitga ega:’payment _ id’,’order _ id #step’,’saga _ id #n’. Ishlov beruvchi:
  • «Koʻrdingizmi?» - TTL/retenshnli dedup-stor (Redis/BD).
  • Agar ko’rgan bo’lsangiz - ilgari hisoblab chiqilgan natijani takrorlaydi yoki no-op qiladi.
Redis eskizi:
lua
-- SET key if not exists; expires in 24h local ok = redis.call("SET", KEYS[1], ARGV[1], "NX", "EX", 86400)
if ok then return "PROCESS" else return "SKIP" end

4. 2 Upsert bazada (idempotent sink)

Yozuvlar UPSERT/ON CONFLICT orqali versiyani/summani tekshirish bilan amalga oshiriladi.

PostgreSQL:
sql
INSERT INTO payments(id, status, amount, updated_at)
VALUES ($1, $2, $3, now())
ON CONFLICT (id) DO UPDATE
SET status = EXCLUDED.status,
updated_at = now()
WHERE payments.status <> EXCLUDED.status;

4. 3 Tranzaksion Outbox/Inbox

Outbox: biznes-tranzaksiya va «nashr etish voqealari» yozuvi bitta DB tranzaksiyasida sodir bo’ladi. Orqa fon nashriyotchisi outbox oʻqiydi va uni brokerga yuboradi → holat va hodisa oʻrtasida hech qanday tafovut yoʻq.
Inbox: kelayotgan buyruqlar uchun’message _ id’va natijani bajarilgunga qadar saqlaymiz; qayta ishlash yozuvni koʻradi va nojoʻya taʼsirlarni takrorlamaydi.

4. 4 Zanjirga konsistent ishlov berish (read → process → write)

Kafka: tranzaksiya «ofsetni o’qib chiqdi → natijalarni yozib oldi → kommit» bitta atom blokiga.
Tranzaksiyasiz: «avval natijani/Inbox, keyin ack yozing»; kreshda dublikat Inbox ko’radi va no-op tugaydi.

4. 5 SAGA/kompensatsiya

Agar idempotentlik mumkin bo’lmasa (tashqi provayder pulni hisobdan chiqarsa), kompensatsiya operatsiyalari (refund/void) va idempotent tashqi APIlardan foydalanamiz (xuddi shu’Idempotency-Key’bilan takroriy’POST’xuddi shunday natijani beradi).


5) Qachon yetarli at-least-once

Kacheylarni/materiallashtirilgan ko’rsatmalarni kalit bo’yicha kompaksiya bilan yangilash.
Hisoblagichlar/metriklar, bu yerda takroriy inkrementatsiya maqbuldir (yoki delta versiyasini saqlaymiz).
Ikkilamchi xat muhim bo’lmagan notifikatsiyalar (baribir kalitni qo’yish yaxshiroqdir).

Qoida: agar dubl biznes ma’nosini o’zgartirmasa yoki osongina topsak → at-least-once + qisman himoya.


6) Unumdorlik va qiymat

Exactly-once (hatto «samarali») qimmatroq: qo’shimcha yozuvlar (Inbox/Outbox), kalitlarni saqlash, tranzaktsiyalar, diagnostika qilish qiyinroq.
At-least-once arzon/oson, yaxshiroq throughput/p99.
Baholang: dubl narxi × dubl ehtimoli vs himoya qiymati.


7) Konfiguratsiyalar va kod namunalari

7. 1 Kafka prodyuser (idempotentlik + tranzaksiyalar)

properties enable.idempotence=true acks=all retries=INT_MAX max.in.flight.requests.per.connection=5 transactional.id=orders-writer-1
java producer.initTransactions();
producer.beginTransaction();
producer.send(recordA);
producer.send(recordB);
// также можно atomically commit consumer offsets producer.commitTransaction();

7. 2 Inbox bilan konsumer (psevdokod)

pseudo if (inbox.exists(msg.id)) return inbox.result(msg.id)
begin tx if!inbox.insert(msg.id) then return inbox.result(msg.id)
result = handle(msg)
sink.upsert(result)     # идемпотентный синк inbox.set_result(msg.id, result)
commit ack(msg)

7. 3 HTTP Idempotency-Key (tashqi API)


POST /payments
Idempotency-Key: 7f1c-42-...
Body: { "payment_id": "p-123", "amount": 10.00 }

Bir xil kalit bilan qayta POST → bir xil natija/maqom.


8) Kuzatish va metrika

’duplicate _ attempts _ total’ - dublni necha marta ushlagan (Inbox/Redis boʻyicha).
’idempotency _ hit _ rate’ - idempotentlik bilan «qutqarilgan» takrorlar ulushi.
’txn _ abort _ rate’ (Kafka/DB) - qaytarishlar ulushi.
’outbox _ backlog’ - nashr ortda qolishi.
’exactly _ once _ path _ latency {p95, p99}’ vs’at _ least _ once _ path _ latency’- qo’shimcha xarajatlar.
Log auditi:’message _ id’,’idempotency _ key’,’saga _ id’,’attempt’.


9) Test-pleybuklar (Game Days)

Qayta jo’natish: Sun’iy taymautlarda prodyuser retrasi.
«Sink va ack»: Inbox/Upsert dublni oldini olishiga ishonch hosil qiling.
Qayta yetkazib berish: brokerda redelivery ko’paytirish; dedupni tekshirish.
Tashqi API idempotentligi: bir xil kalitli takroriy POST - bir xil javob.
Etakchi oʻzgarishi/tarmoq uzilishi: Kafka tranzaksiyalarini/konsumerlarning xatti-harakatlarini tekshirish.


10) Anti-patternlar

Transportga tayanish: «Bizda Kafka exactly-once bilan, demak kalitsiz bo’lishi mumkin» - yo’q.
No-op ack yozishdan oldin: ochildi, lekin sink yiqildi → yo’qotish.
Jitterli DLQ/retraylarning yo’qligi: cheksiz takrorlash va bo’ron.
Tabiiy kalitlar o’rniga tasodifiy UUID: hech narsa demontaj qilinmaydi.
Inbox/Outbox prod jadvallari bilan indekssiz aralashtirish: issiq blokirovka va p99-quyruqlar.
Tashqi provayderlarda idempotent APIsiz biznes-operatsiyalar.


11) Tanlov chek-varaqasi

1. Dubl narxi (pul/yuridik/UX) vs himoya narxi (yashirin/murakkablik/qiymat).
2. Hodisa/operatsiyaning tabiiy kaliti bormi? Agar yo’q bo’lsa, barqarorni o’ylab toping.
3. Sink Upsert/versiyalashni qoʻllab-quvvatlaydimi? Aks holda - Inbox + kompensatsiyalar.
4. Global tranzaksiyalar kerakmi? Agar yo’q bo’lsa, SAGA’da segmentlang.
5. Takrorlash/uzoq muddatli retenshn talab qilinadimi? Kafka + Outbox. Tezkor RPC/past kechikish kerakmi? NATS + Idempotency-Key.
6. Ko’p tenantlik va kvotalar: kalitlar/bo’shliqlarni izolyatsiya qilish.
7. Kuzatish darajasi: idempotency va backlog metriklari kiritilgan.


12) FAQ

Q: «Matematik» exactly-once end-to-end ga erishish mumkinmi?
A: Faqat butun yo’lda bitta konsistent saqlash va tranzaksiyalar bilan tor stsenariylarda. Umumiy holatda - yo’q; idempotentlik orqali exactly-once’dan samarali foydalaning.

Q: Nima tezroq?
A: At-least-once. Exactly-once tranzaksiyalarni qoʻshadi/kalitlarni saqlash → yuqori p99 va qiymati.

Q: Idempotentlik kalitlarini qayerda saqlash kerak?
A: TTL bilan tezkor stor (Redis) yoki Inbox jadvali (PK = message _ id). To’lovlar uchun - ko’proq (kunlar/haftalar).

Q: TTL dedup kalitlarini qanday tanlash mumkin?
A: Minimal = qayta yetkazib berishning maksimal vaqti + operatsion zaxirasi (odatda 24-72 soat). Moliya uchun - ko’proq.

Q: Agar Kafka’da compaction bo’lsa, menga kalit kerakmi?
A: Ha. Compaction saqlashni kamaytiradi, lekin sizning sinkingizni idempotent qilmaydi.


13) Yakunlar

At-least-once - transportning asosiy, ishonchli semantikasi.
Exactly-once biznes effekti sifatida Idempotency-Key, Inbox/Outbox, Upsert/versiya, SAGA/kompensatsiya darajasida erishiladi.
Tanlash - bu ikkilanish xavfi qiymatining murosasidir. Tabiiy kalitlarni loyihalashtiring, sinklarni idempotent qiling, kuzatish qobiliyatini qo’shing va muntazam ravishda o’yin kunlarini o’tkazing - shunda retray va nosozliklar bo’lganda ham payplaynlaringiz oldindan aytib bo’ladigan va xavfsiz bo’ladi.

Contact

Biz bilan bog‘laning

Har qanday savol yoki yordam bo‘yicha bizga murojaat qiling.Doimo yordam berishga tayyormiz.

Integratsiyani boshlash

Email — majburiy. Telegram yoki WhatsApp — ixtiyoriy.

Ismingiz ixtiyoriy
Email ixtiyoriy
Mavzu ixtiyoriy
Xabar ixtiyoriy
Telegram ixtiyoriy
@
Agar Telegram qoldirilgan bo‘lsa — javob Email bilan birga o‘sha yerga ham yuboriladi.
WhatsApp ixtiyoriy
Format: mamlakat kodi va raqam (masalan, +998XXXXXXXX).

Yuborish orqali ma'lumotlaringiz qayta ishlanishiga rozilik bildirasiz.