GH GambleHub

Кайталоо стратегиялары жана идемпотенттүүлүк

1) Эмне үчүн керек

Тармактардагы мүчүлүштүктөр - норма: таймауттар, transient-каталар, тармактык флаппингдер, ашыкча жүктөө. Retrains ишенимдүүлүгүн гана жогорулатат:

1. кайталоо коопсуз (idempotenten),

2. кайталоолордун ортосунда сакталган,

3. көз карандылыктын лимиттери/квоталары жана "ден соолук".

максаты - effectively-once бизнес-бүтүмдөрдүн деъгээлинде жүрүм-туруму эч кандай жалган дубль жана жарыш.

2) Жеткирүү семантикасы таксономиясы

At-most-once: кайталоо жок, жоготуу коркунучу (логин, fire-and-forget).
At-least-once: мүмкүн дубликат → керектөөчүнүн демпотенттик керек (көпчүлүк кезек, Webhuke).
Effectively-once: дубликаттар мүмкүн, бирок туура дедуплициялоо (ачкычтар, бүтүмдөр, outbox).

3) Качан ретрациялоо керек жана качан

Retrait мааниси бар: '408', '429' ('Retry-After' ылайык), '425' (Too Early), '499' (периметрде client closed), '5xx', '504', тармактык таймауттар/ажырымдар, '502' шлюз, "connection reset".
Суроо-талапты өзгөртпөстөн артка кайтарылбайт: '400/ 401/403/404/422'.
Талаштуу учурлар: '409 Conflict' (адатта ретраим эмес; адегенде операциянын статусун окуйбуз/ниетин кайталайбыз).

4) Таймауттар, backoff жана життер

4. 1 Эрежелер

Биринчи таймаут, андан кийин ретраиялар: ар бир суроо-талап "deadline" болушу керек.
Exponential backoff: 'delay _ n = base 2 ^ n', чектөө 'max _ delay'.
Jitter милдеттүү: "келесоо синхрондуу толкундарды" чечүү үчүн кокустук кошуу.

4. 2 Jitter үлгүлөрү

Full jitter: 'sleep = rand (0, base2 ^ n)' - эң жакшы жалпы тандоо.
Decorrelated jitter: 'sleep = min (max_delay, rand (base, sleep_prev3))' - узак диалогдор үчүн.
Equal jitter: 'sleep = base2 ^ n/2 + rand (0, base2 ^ n/2)' - жумшак вариация.

4. 3 Retry-budget

Retrains үлүшүн чектөө:
  • `retry_budget_per_min = max(α success_rps, floor β)`; адатта 'α = 0. 1–0. 2`.
  • Бюджет түгөнгөндө - fail-fast/circuit breaker "open".

5) rate limiting жана Circuit Breaker менен өз ара

Урматтоо 'Retry-After', 'RateLimit-Reset' жана бэк-оффко карап көрөлү.
Жогорку '5хх '/тайм менен - ретрациялардын жыштыгын жана жалпы параллелизмди азайтыңыз.

Circuit breaker:
  • Half-open: чектелген үлгү берет.
  • Open: дароо четке кагат (ресурстарды үнөмдөйт).
  • Closed: кадимки иш.
  • Write операцияларында 409/503 агрессивдүү ретрансляторлорду айлантканга караганда так шилтеме менен кайтаруу жакшы.

6) Write-бүтүмдөрдү аныктоо

6. 1 Жалпы идея

Бирдей ниет → бир натыйжасы. Негиздери - идемпотенттүүлүктүн ачкычы жана аткаруу жазууларынын сактагычы.

6. 2 HTTP-контракт

Кардар төмөнкү аталышты жөнөтөт:

Idempotency-Key: 7a6b7f9e-2a46-4d0b-9c3a-2b30e1c3c9e3
Idempotency-Key-Expiry: 24h # optional
Сервер:
  • биринчи ийгиликтүү аткарууда сактайт (ачкыч → натыйжасы, абалы, дене хэш);
  • кайталаганда мурунку жоопту жана 'Idempotency-Replay: true' аталышын кайтарат;
  • дене карама-каршы келгенде (ошол эле ачкыч, бирок башка payload) - '409 Conflict'.

6. 3 сактоо жана TTL

Таблица/ачкыч мааниси: 'idempotency _ key', 'request _ hash', 'result', 'status', 'expiry _ at'.
TTL = Мүмкүн болгон кайталоо жана кеч жеткирүү терезеси (адатта төлөмдөр үчүн 24-72 саат).
'idempotency _ key' боюнча индекстер; жогорку жүк үчүн - хеш боюнча шардана.

6. 4 Схема мисал (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 иштеп псевдокод

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" үлгүлөрү

Transactional Outbox: бизнес-окуяны жазуу жана фон релейери аркылуу ошол эле DB транзакциясынан билдирүү жөнөтүү; керектөөчү idempotenten.
Керектөөчүдө Inbox/Processed-table: double четке 'event _ id' сактоо.
Kafka боюнча Exactly-once ≠ бизнесте exactly-once: ал тургай, EOS өндүрүүчүсү/колдонуучу колдонмо логика дагы эле idempotent болушу керек.
Компенсациялык транзакциялар (Saga): эгерде кадамдар артка чегинип, терс таасирлерди жаратса, системаны инвариантка кайтарабыз.

8) Жеке учурлар: төлөмдөр жана финансылык операциялар

Strong idempotency: ачкыч операциянын логикасына байланган (мисалы, 'external _ payment _ id').
PSP боюнча deduplication: сактагыла 'merchant _ reference' → кайталаганда PSP мурунку натыйжасын кайтарат.
"Кардардан" ретраи: "Idempotency-Key" болгондо гана уруксат берүү, антпесе кош эсептен чыгаруу коркунучу.
Атаандаштык: аткаруу учурунда "эсепке/куралга/келишимге" бөгөт коюу; кайталаганда 409/423 кайтарыңыз.
Байкоо: метрика 'idempo _ replay _ total', 'idempo _ conflict _ total'.

9) Вебхактар жана тышкы чакырыктар

HMAC кол тамгалар жана убакыт терезе; биринчи текшерүү, андан кийин иштетүү.
Жөнөтүүчүнүн Retraes: экспоненциалдык backoff + Jitler, 'max _ attempts' жана DLQ.
Керектөөчү - idempotent: 'event _ id' → таблица/in-memory cache; "тыкан" тартип кепилденген эмес.
коддору: 2xx = ийгиликтүү, 4xx = кайталап жок, 5xx/убакыт = кайталап.

10) Кезектер жана фон милдеттери

Ат-least-once демейки → кайталоо сөзсүз болот.
'task _ id '/' event _ id' жана аткаруу статусун сактаңыз; учурда - кыска жол "replay".
DLQ жана poison-messages: аракет эсептегич, карантин, кол талдоо.
Атаандаштык лимиттер (семафорлор) жана демпотенттик воркерлер.

11) Версиялоо жана "табигый" ачкычтар

Натуралдык ачкычтар (эсеп номери + дата + документ номери) кайталоого туруктуулукту жогорулатат.
Схеманы/версияны алмаштырууда 'Idempotency-Key' версиясынын ачкычын же суроо-талаптын хэшин киргизиңиз.

12) HTTP аталыштары жана кардарга

'Idempotency-Key', 'Idempotency-Replay', 'Retry-After', 'Prefer: wait = <sec>' (узакка созулган операцияларда), 'If-Match '/' ETag' (оптимисттик блоктор).
409 "Retry-After" валиддик менен 425/429/503 ачкычтын кагылышында.
"Узун" операциялар үчүн - асинхрондук статусту кабыл алуу (статус ресурсуна '202 Accepted' + 'Location').

13) сыноо жана башаламандык жагдайлар

Negative-тесттер: эки жолу жөнөтүү, башка орган менен кайталоо, бир нече саат.
тартип бузуу: 't2' мурда келет 't1'.
Enjeksiyon убакыт/' RST '/' EOF ', жарым-жартылай суроолор (slow-POST).
кулаган сактоо idempotency → жүрүм-fail-closed (эки эсепти караганда жакшы баш тартуу).

14) Метрика жана Алерт

`retries_total{reason}`, `retry_budget_used{route}`, `backoff_seconds_bucket`.
`idempo_replay_total`, `idempo_conflict_total`, `duplicate_detected_total`.
409/425/429/5xx маршруттар боюнча үлүшү; p95/p99 "ийгиликке чейин убакыт" ретра менен.
Alerty: burn-rate бюджети retrai, чыр-чатактар ​ ​ демпотенттик өсүшү, DLQ өсүшү.

15) Антипаттерндер

Бардык каталарды ретрациялоо.
Жок Jitter → синхрондуу толкун retrains.
TTL жана тазалоо жок узак мөөнөттүү ачкычтар.
Committee терс таасиринен кийин натыйжасын сактоо (outbox бузуу).
Логи жок 'trace _ id '/' idempotency _ key' → форензия мүмкүн эмес.
Write операцияларында агрессивдүү параллелдүү ретрациялар.

16) Prod-даярдык чек тизмеси

  • Бирдиктүү саясат: эмне ретраим, эмне жок; кардарга коддор жана кеңештер.
  • экспоненциалдуу backoff + full jitter; берилген 'retry _ budget'.
  • Келишим 'Idempotency-Key' + TTL менен натыйжаларды сактоо.
  • окуялар үчүн Outbox/Inbox; DLQ; атаандаштык лимиттери.
  • circuit breaker менен бириктирүү, respect 'Retry-After'.
  • Метрика/retrains/дубликат/чыр-чатактар боюнча алерт.
  • Башаламандык сыноолордун топтому жана тармактык каталарды эмуляциялоо.
  • Кардарлар үчүн документтер: бэк-офф мисалдары жана статустар.

17) TL; DR

Ретрайдар демпотенттик менен гана пайдалуу. 'Idempotency-Key' жана натыйжаларды сактоо киргизүү, Jitter жана retry-budget менен экспоненциалдык backoff колдонуу, 'Retry-After' урматтоо, circuit breaker менен бириктирүү. окуялар үчүн - outbox/inbox; төлөмдөр үчүн - катуу дедупликация жана бөгөт коюу. Ретраларды жана чыр-чатактарды өлчөө, дубликаттарды жана таймауттарды сыноо.

Contact

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

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

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

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

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

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