GH GambleHub

Exactly-once vs At-least-once

1) Эмне үчүн семантиканы талкуулоо керек

Жеткирүү семантикасы алуучу каталар жана ретрациялар учурунда билдирүүнү канчалык көп көрөрүн аныктайт:
  • At-most-once - кайталоо жок, бирок жоготуу мүмкүн (сейрек кабыл алынат).
  • At-least-once - биз жоготпойбуз, бирок дубликаттар болушу мүмкүн (көпчүлүк брокерлердин/кезектердин дефолту).
  • Exactly-once - ар бир билдирүү байкалган таасири боюнча так бир жолу иштетилет.

Негизги чындык: глобалдык бүтүмдөр жана синхрондуу ырааттуулук жок бөлүштүрүлгөн дүйнөдө "таза" end-to-end exactly-once кол жеткис. Биз натыйжалуу exactly-once куруп: транспорт боюнча кайталоо жол, бирок байкалган таасири "бир жолу сыяктуу" болгон жол менен empotent иштетүү.


2) Бузулуулардын модели жана дубликаттар кайда пайда болот

Кайталоолор улам пайда болот:
  • Жоготуулар ack/commit (продюсер/брокер/консюмер "уккан жок" ырастоо).
  • Лидерлерди кайра шайлоо/репликалар, тармактык ажырымдардан кийин калыбына келтирүү.
  • Ар кандай сайттарда таймауттар/ретрайлер (кардар → брокер → консюмер → синк).

Тергөө: транспорттун "уникалдуулугуна" таянууга болбойт. Эффекттерди башкарабыз: БДга жазуу, акчаны эсептен чыгаруу, кат жөнөтүү ж.б.


3) жөнөтүүчүлөр жана чынында эмне үчүн Exactly-once

3. 1 Kafka

кирпич берет:
  • Idempotent Producer (`enable. idempotence = true ') - өндүрүүчүнүн ретрага тарапта дубль болтурбоо.
  • Транзакциялар - атомдук түрдө бир нече партияларга билдирүүлөрдү жарыялайт жана керектөө офсеттерин (үлгү read-process-write "өткөрбөстөн").
  • Compaction - ачкычтын акыркы маанисин сактайт.

Бирок "чынжыр аягы" (Синк: BD/төлөм/почта) дагы эле боштукту талап кылат. Болбосо, иштетүү эки эсе таасир алып келет.

3. 2 NATS / Rabbit / SQS

демейки - ack/redelivery менен at-least-once. Exactly-once колдонмо деъгээлинде жетишилет: ачкычтар, дедуп, upsert.

Жыйынтык: Exactly-once транспорт ≠ exactly-once таасири. Акыркысы иштетүүчүдө жасалат.


4) Кантип натыйжалуу exactly-once at-least-once үстүнө куруу

4. 1 Idempotency ачкычы (idempotency key)

Ар бир команда/окуя табигый ачкычын алып: 'payment _ id', 'order _ id #step', 'saga _ id #n'. Иштеп чыгуучу:
  • "Көрдүңбү?" - Дедуп-стор (Redis/DD) менен TTL/retenshn.
  • Эгерде көрдүм - мурда эсептелген натыйжаны кайталайт же no-op кылат.
Redis эскиз:
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 базасы (Emempotent Синк)

Жазуулар UPSERT/ON CONFLICT версиясын/суммасын текшерүү менен жүргүзүлөт.

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 Транзакциялык Outbox/Inbox

Outbox: бизнес-бүтүм жана жазуу "жарыялоо окуялар" бир бүтүм DD өтөт. Фон жарыялоочу outbox окуп, брокерге жөнөтөт → мамлекет менен окуянын ортосунда эч кандай айырмачылыктар жок.
Inbox: кирген командалар үчүн 'message _ id' жана натыйжасы аткарылганга чейин сакталат; кайра иштетүү жазууну көрөт жана терс таасирлерин кайталабайт.

4. 4 консистенттик чынжыр иштетүү (read → process → write)

Kafka: транзакция "окулган офсет → жазылган жыйынтыктар → коммит" бир атомдук блокто.
Транзакцияларсыз: "биринчи жыйынтыкты/Inbox, андан кийин ack жазыңыз"; crash кайталанма Inbox көрөт жана no-op аяктайт.

4. 5 SAGA/компенсация

Демпотенттик мүмкүн болбогондо (тышкы провайдер акчаны эсептен чыгарып салган) компенсациялык операцияларды (refund/void) жана демпотенттик тышкы APIлерди (ошол эле "Idempotency-Key" менен кайталанган "POST" ошол эле жыйынтыкты берет) колдонобуз.


5) Качан жетиштүү ат-least-once

Кэш/материалдаштырылган идеяларды ачкыч компакциясы менен жаңыртуу.
Кайра инкрементация алгылыктуу болгон эсептегичтер/метриктер (же версия менен дельталарды сактайбыз).
экинчи кат маанилүү эмес ноталар (жакшы дагы ачкычын коюп).

Эреже: Эгер дубль бизнес маанисин өзгөртпөсө же оңой табылса → at-least-once + жарым-жартылай коргоо.


6) аткаруу жана наркы

Exactly-once (ал тургай, "натыйжалуу") кымбат турат: кошумча жазуу (Inbox/Outbox), сактоо ачкычтары, бүтүмдөр, татаал диагностика.
At-least-once арзан/жөнөкөй, жакшы throughput/p99.
баа: эки эсе баасы × эки эсе ыктымалдыгы vs коргоо наркы.


7) Конфигурация жана код мисалдары

7. 1 Kafka Продюсер (idempotentity + бүтүмдөр)

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 менен Consumer (psevdocode)

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 (тышкы API)


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

Ошол эле ачкыч менен кайталап POST → Ошол эле натыйжасы/абалы.


8) Байкоо жана метрика

'duplicate _ attempts _ total' - канча жолу эки жолу кармалган (Inbox/Redis боюнча).
'idempotency _ hit _ rate' - "сакталган" кайталоолордун үлүшү.
'txn _ abort _ rate' (Kafka/DD) - кайтарымдардын үлүшү.
'outbox _ backlog' - жарыялоонун артта калышы.
'exactly _ once _ path _ latency {p95, p99}' vs 'at _ least _ once _ path _ latency' - кошумча чыгымдар.
Логдордун аудити: 'message _ id', 'idempotency _ key', 'saga _ id', 'attempt'.


9) Test Playbook (Оюн күндөрү)

Кайталап жөнөтүү: жасалма тайм менен өндүрүүчүнүн ретрасы.
"Синк жана ACK" ортосунда Crash: Inbox/Upsert кош алдын алуу үчүн.
Кайра жеткирүү: брокердин redelivery көбөйтүү; дедуп текшерүү.
Тышкы APIs ыктымалдыгы: ошол эле ачкыч менен кайталап POST - бирдей жооп.
Лидер өзгөртүү/тармактын үзүлүшү: Кафка транзакцияларын/консультанттардын жүрүм-турумун текшерүү.


10) Анти-үлгүлөрү

транспорт таянуу: "Биз exactly-once менен Kafka, анда ачкычы жок болот" - жок.
No-op ack чейин жазуу: ачылып, бирок синк түшүп → жоготуу.
Жок DLQ/retrains менен Jitter: чексиз кайталоо жана бороон.
Табигый ачкычтардын ордуна кокустук UUID: deduplication эч нерсе жок.
Индекстери жок прод-таблицалар менен Inbox/Outbox аралаштыруу: ысык блоктор жана p99-куйруктары.
Тышкы провайдерлерде идемпотенттик API жок бизнес-операциялар.


11) Тандоо чек-тизмеси

1. double баасы (акча/юридикалык/UX) vs коргоо баасы (жашыруун/татаалдыгы/наркы).
2. Иш-чаранын/операциянын табигый ачкычы барбы? Эгер жок болсо - туруктуу келип.
3. Sink Upsert/чыгаруу колдойт? Болбосо - Inbox + ордун толтуруу.
4. Глобалдык транзакциялар керекпи? Эгер жок болсо - SAGA боюнча сегментти.
5. реплика/узак retenshn талап кылынат? Kafka + Outbox. тез RPC/төмөн кечигүү керек? NATS + Idempotency-Key.
6. Көп тенанттуулук жана квота: ачкычтарды/мейкиндиктерди изоляциялоо.
7. Байкоо: idempotency жана backlog метриктер кирет.


12) FAQ

Q: "математикалык" жетүү мүмкүнбү exactly-once end-to-end?
A: бир консистенттик сактоо жана бүтүмдөр менен тар жагдайда гана жол. Жалпы учурда - жок; натыйжалуу жол-жоболоштуруу аркылуу exactly-once колдонуу.

Q: эмне тезирээк?
A: At-least-once. Exactly-once транзакцияларды/ачкычтарды сактоону кошот → p99 жогору жана баасы.

Q: Кайда демпотенттик ачкычтарын сактоо керек?
A: Fast Store (Redis) менен TTL, же таблица Inbox (PK = message _ id). Төлөмдөр үчүн - узак (күн/жума).

Q: TTL дедуп ачкычтарды кантип тандоо керек?
A: минималдуу = максималдуу кайра жеткирүү убактысы + иш запасы (адатта 24-72 саат). Каржы үчүн - көбүрөөк.

Q: Мен Kafka ачкычы боюнча compaction болсо, ачкыч керекпи?
A: Ооба. Compaction сактоону азайтат, бирок сиздин синк болбогон кылат.


13) Натыйжалары

At-least-once - транспорттун негизги, ишенимдүү семантикасы.
Exactly-once бизнес таасири иштеп деъгээлинде жетишилет: Idempotency-Key, Inbox/Outbox, Upsert/версия, SAGA/ордун толтуруу.
Тандоо - бул компромисс баасы тобокелдик эки эсе жөнөкөй иш. Табигый ачкычтарды долбоорлоо, көгүчкөндөрдү демпотенттик кылуу, байкоону кошуу жана оюн күндөрүн үзгүлтүксүз өткөрүү - анда сиздин пайплайндарыңыз ретрациялардын жана ийгиликсиздиктердин бороонунда да алдын ала айтууга жана коопсуз болот.

Contact

Биз менен байланышыңыз

Кандай гана суроо же колдоо керек болбосун — бизге кайрылыңыз.Биз дайым жардам берүүгө даярбыз!

Интеграцияны баштоо

Email — милдеттүү. Telegram же WhatsApp — каалооңузга жараша.

Атыңыз милдеттүү эмес
Email милдеттүү эмес
Тема милдеттүү эмес
Билдирүү милдеттүү эмес
Telegram милдеттүү эмес
@
Эгер Telegram көрсөтсөңүз — Emailден тышкары ошол жактан да жооп беребиз.
WhatsApp милдеттүү эмес
Формат: өлкөнүн коду жана номер (мисалы, +996XXXXXXXXX).

Түшүрүү баскычын басуу менен сиз маалыматтарыңыздын иштетилишине макул болосуз.