Exactly-once vs At-least-once
1) Semantikleri näme üçin ara alyp maslahatlaşmaly?
Eltip bermegiň semantikasy alyjynyň şowsuzlyklarda we retralarda habary näçe gezek görjekdigini kesgitleýär:- At-most-once - gaýtalanmazdan, ýöne ýitmek mümkin (seýrek kabul ederlikli).
- At-least-once - ýitirmeýäris, ýöne dublikatlar bolup biler (dellallaryň/nobatlaryň köpüsiniň defolty).
- Exactly-once - her habar syn edilýän täsir nukdaýnazaryndan takmynan bir gezek işlenilýär.
Esasy hakykat: global amallar we sinhron ylalaşyksyz paýlanan dünýäde "arassa" gutarnykly hereket etmek mümkin däl. Biz netijeli exactly-once gurýarys: ulagda gaýtalanmalara ýol berýäris, ýöne gözegçilik edilýän täsir "bir gezek ýaly" bolar ýaly empotent bejergisini edýäris.
2) Şowsuzlyklaryň nusgasy we dublikatlar nirede ýüze çykýar
Şu sebäpli gaýtalanýar:- ack/commit ýitgileri (prodýuser/broker/konsumer tassyklamany "eşitmedi").
- Liderleriň/replikalaryň gaýtadan saýlawlary, tor arakesmelerinden soň dikeldişler.
- Islendik ýerlerde wagt/retraew (müşderi → broker → konsumer → sink).
Netije: transportyň "eltilmeginiň özboluşlylygyna" bil baglap bolmaz. Täsirleri dolandyrýarys: DB-e ýazmak, pullary hasapdan çykarmak, hat ibermek we ş.m.
3) Üpjün edijilerde Exactly-once we hakykatda näme
3. 1 Kafka
Kerpiç berýär:- Idempotent Producer (`enable. idempotence = true ') - retrada prodýuseriň tarapynda dubllaryň öňüni alýar.
- Amallar - birnäçe partiýa we jemleýji sarp ediş ofsetlerine ("geçişsiz" read-process-write patterni) atomiki habarlar çap edýär.
- Compaction - iň soňky bahany açarda saklaýar.
Emma "zynjyryň soňy" (sink: BD/töleg/poçta) henizem idempotentligi talap edýär. Otherwiseogsam, prosessor goşa täsir eder.
3. 2 NATS / Rabbit / SQS
Variant - ack/redelivery bilen at-least-once. Exactly-once programma derejesinde gazanylýar: açarlar, dedup-stor, upsert.
Netije: Exactly-once transporty ≠ exactly-once effekti. Iň soňkusy prosessorda edilýär.
4) At-least-once-iň üstünde netijeli exactly-once nädip gurmaly
4. 1 Idempotent açary (idempotency key)
Her bir topar/waka tebigy açary göterýär: 'payment _ id', 'order _ id #step', 'saga _ id #n'. Bejeriji:- "Eýýäm gördüňizmi?" - TTL/retenşn bilen dup-stor (Redis/BD).
- Eger görse - öň hasaplanan netijäni gaýtalaýar ýa-da no-op edýär.
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 maglumatlar bazasynda (idempotent sink)
Ýazgylar UPSERT/ON CONFLICT arkaly wersiýasyny/mukdaryny barlamak bilen amala aşyrylýar.
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 Geleşik Outbox/Inbox
Outbox: iş amallary we "neşir etmek üçin wakalar" ýazgysy bir DB amalynda bolup geçýär. Fon neşirçisi outbox okaýar we dellalyna iberýär → ýagdaý bilen wakanyň arasynda tapawut ýok.
Inbox: Gelen toparlar üçin 'message _ id' we netijäni ýerine ýetirilýänçä saklaýarys; gaýtadan işlemek ýazgyny görýär we zyýanly täsirleri gaýtalamaýar.
4. 4 Zynjyry bejermek (read → process → write)
Kafka: geleşik "okadym ofset → ýazdym netijeleri → kommit" bir atom blokuna.
Geleşiksiz: "ilki netijäni ýazyň/Inbox, soň ack"; kreşde dublikat Inbox görer we no-op gutarar.
4. 5 SAGA/kompensasiýa
Idempotentlik mümkin bolmadyk mahalynda (daşarky üpjün ediji pullary hasapdan çykaranda) öwezini dolmak amallaryny (refund/void) we idempotentli daşarky API-leri ulanýarys (şol "Idempotency-Key" bilen gaýtalanýan "POST" şol bir netijäni berýär).
5) At-least-once ýeterlik bolanda
Açar kompaksiýasy bilen nagt/materiallaşdyrylan görkezmeleri täzelemek.
Hasaplaýjylar/metrikler, bu ýerde gaýtalanýan inkrementasiýa kabul ederlikli (ýa-da wersiýasy bolan deltalary saklaýarys).
Ikinji hat möhüm däl bolan bellikler (her niçigem bolsa açary goýmak has gowudyr).
Düzgün: eger goşa iş manysyny üýtgetmese ýa-da aňsatlyk bilen tapyp bilsek → at-least-once + bölekleýin gorag.
6) Öndürijiligi we bahasy
Exactly-once (hatda "täsirli") has gymmat: goşmaça ýazgy (Inbox/Outbox), açarlary saklamak, amallar, anyklamak has kyn.
At-least-once arzan/aňsat, has gowy throughput/p99.
Baha beriň: goşa bahasy × goşa ähtimallygy vs gorag bahasy.
7) Konfigurasiýa we kod mysallary
7. 1 Kafka prodýuser (idempotentlik + amallar)
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 bilen 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 (daşarky API)
POST /payments
Idempotency-Key: 7f1c-42-...
Body: { "payment_id": "p-123", "amount": 10.00 }
Şol bir açar bilen gaýtadan POST → şol bir netije/status.
8) Synlamak we metrika
'duplicate _ attempts _ total' - näçe gezek iki gezek tutuldy (Inbox/Redis boýunça).
'idempotency _ hit _ rate' - idempotentlik bilen "halas edilen" gaýtalamalaryň paýy.
'txn _ abort _ rate' (Kafka/DB) - yzyna gaýtarmagyň paýy.
'outbox _ backlog' - neşiriň yza galmagy.
'exactly _ once _ path _ latency {p95, p99}' vs 'at _ least _ once _ path _ latency' - goşmaça çykdajylar.
Log barlagy: 'message _ id', 'idempotency _ key', 'saga _ id', 'attempt'.
9) Game Days (Game Days)
Iberişiň gaýtalanmagy: emeli wagtlarda öndürijiniň retrasy.
"Sink & ack" aralygy: Inbox/Upsert goşa päsgel berýändigine göz ýetiriň.
Gaýtadan eltip bermek: brokerde redelivery artdyrmak; dedupy barlamak.
Daşarky API-leriň gidempotentligi: şol bir açar bilen gaýtalanýan POST - birmeňzeş jogap.
Lideriň üýtgemegi/toruň kesilmegi: Kafka amallaryny/konsumerleriň özüni alyp barşyny barlamak.
10) Anti-patternler
Transporta bil baglamak: "Bizde exactly-once bilen Kafka bar, şonuň üçin açarsyz edip bilersiňiz" - ýok.
No-op ack ýazylmazdan ozal: açyldy, ýöne sink ýykyldy → ýitgi.
DLQ/jitter retraýalarynyň ýoklugy: tükeniksiz gaýtalanmalar we tupan.
Tebigy açarlaryň ýerine tötänleýin UUID: duplizirlemek üçin hiç zat ýok.
Inbox/Outbox prod tablisalary bilen indekssiz garyşdyryň: gyzgyn gulplar we p99 guýruklar.
Daşarky üpjün edijilerde idempotent API-siz iş amallary.
11) Saýlamagyň çek-sanawy
1. Goşa bahasy (pul/hukuk/UX) vs gorag bahasy (gizlinlik/çylşyrymlylyk/bahasy).
2. Wakanyň/amalyň tebigy açary barmy? Eger ýok bolsa, durnukly oýlap tapyň.
3. Sink Upsert/wersiýalanmagy goldaýarmy? Otherwiseogsam - Inbox + kompensasiýa.
4. Global amallar gerekmi? Ýok bolsa, SAGA-da bölüň.
5. Replika/uzyn retenşn gerek? Kafka + Outbox. Çalt RPC/pes gijikdirme gerekmi? NATS + Idempotency-Key.
6. Köp tenantlyk we kwotalar: açarlaryň/giňişlikleriň izolýasiýasy.
7. Syn edilişi: idempotency we backlog metrikleri goşuldy.
12) FAQ
Q: "Matematiki" exactly-once end-to-end gazanyp bolarmy?
A: Diňe tutuş ýolda bir konsistent ammar we amallar bilen dar ssenariýalarda. Umumy ýagdaýda - ýok; idempotentlik arkaly netijeli exactly-once ulanyň.
S: Has çalt näme?
A: At-least-once. Exactly-once geleşikleri goşýar/açarlary saklamak → p99-dan ýokary we bahasy.
Q: Idempotentlik açarlary nirede saklanmaly?
A: TTL bilen çalt stor (Redis) ýa-da Inbox tablisasy (PK = message _ id). Tölegler üçin - has uzyn (günler/hepdeler).
Q: TTL dup açarlaryny nädip saýlamaly?
A: Iň az = gaýtadan eltmegiň iň köp wagty + amal ätiýaçlygy (adatça 24-72 sagat). Maliýe üçin - has köp.
Q: Kafka açary boýunça compaction bar bolsa, açar gerekmi?
A: Hawa. Compaction ammaryňyzy azaldar, ýöne sinkiňizi pes etmez.
13) Netijeler
At-least-once - transportyň esasy, ygtybarly semantikasy.
Iş täsiri hökmünde Exactly-once prosessor derejesinde gazanylýar: Idempotency-Key, Inbox/Outbox, Upsert/wersiýa, SAGA/kompensasiýa.
Saýlamak, iki gezek işlemegiň töwekgelçiliginiň bahasy bilen ylalaşmakdyr. Tebigy açarlary dizaýn ediň, mawy duýgur ediň, syn ediň we oýun günlerini yzygiderli geçiriň - şonda paýlaýjlaryňyz retraý we şowsuzlyk tupany bilen hem öňünden aýdyp boljak we howpsuz bolar.