GH GambleHub

Саги та розподілені транзакції

Сага - це довготривала бізнес-транзакція, розбита на послідовність локальних кроків у різних сервісах/сховищах. Кожен крок має компенсуючу дію, яка відкочує ефект кроку при частковому провалі. На відміну від 2PC/3PC, саги не утримують глобальні блокування і підходять для мікросервісів, мульти-регіонів і високих навантажень, де допустима eventual consistency.


1) Коли вибирати саги (а коли - ні)

Підходить:
  • Тривалі/багатокрокові бізнес-процеси (замовлення → оплата → резерв → доставка).
  • Різні домени і сховища, де немає загальної транзакції.
  • Потрібна висока доступність і горизонтальне масштабування.
Не підходить:
  • Тверда ACID-атомарність критична (наприклад, перенесення великих сум у межах одного реєстру).
  • Немає чіткої компенсованості (не можна «раз-зарезервувати» або скасувати ефект).
  • Юридичні/регуляторні обмеження вимагають суворої ізоляції і «моментального» інваріанта.

2) Моделі саг

1. Оркестрація (Saga Orchestrator): центральний координатор управляє кроками і компенсаціями.

Плюси: явний потік, контроль помилок, спрощена телеметрія.
Мінуси: точка централізації, ризик «товстого» координатора.

2. Хореографія (Choreography): немає центру - кроки ініціюються подіями («сервіс А зробив X → сервіс Б реагує»).

Плюси: слабка зв'язність, просте масштабування.
Мінуси: складніше відстежувати/дебажити потік, ризик «розростання» правил.

3. TCC (Try-Confirm/Cancel): кожен крок - «резервування» (Try), потім підтвердження (Confirm) або скасування (Cancel).

Плюси: ближче до псевдо-двофазного протоколу, керовані ресурси.
Мінуси: дорожче в реалізації інтерфейсів; вимагає таймаутів власників «Try».


3) Проектування кроку і компенсації

Інваріанти: чітко сформулюйте, що повинно бути істинно «до/після» кроку (наприклад, «залишок ≥ 0»).
Компенсація ≠ зворотна транзакція: це логічна дія, що скасовує бізнес-ефект (refund, release, restore).
Ідемпотентність: і крок, і компенсатор повинні безпечно повторюватися (по'operation _ id').
Таймаути: кожен крок має deadline; прострочення ініціює компенсації.
Безповоротні ефекти: фіксуйте їх окремо (повідомлення, e-mail) і допускайте «best effort».


4) Узгодженість і порядок

Eventual consistency: користувачі можуть бачити тимчасові розбіжності; UX - з «очікуванням «/спінерами/статусами.
Порядок за ключем: комутаційні кроки групуйте за бізнес-ключем (order_id), щоб впорядковувати події.
Дедуплікація: зберігайте журнал обробок ('operation _ id'→ статус) з TTL.


5) Транспорт і надійність

Outbox pattern: запис події в локальну таблицю «outbox» всередині тієї ж транзакції, а потім асинхронна публікація в шину.
Inbox/Idempotency store: на стороні споживача - журнал вже оброблених повідомлень.
Exactly-once ефективно: «outbox + idempotent consumer» дає практичне «рівно один раз».
DLQ: для «отруйних» повідомлень з багатою мета-інформацією і безпечним редрайвом.


6) Політики помилок, ретраї, backoff

Повторюємо тільки ідемпотентні кроки; операції запису - з'Idempotency-Key'.
Експоненціальний backoff + джиттер; обмеження спроб і сумарного дедлайну саги.
При системній деградації - Circuit Breaker і graceful degradation (наприклад, скасувати другорядну фіч-частину саги).
Бізнес-конфлікти («409») - повтор після узгодження або компенсувати і завершити.


7) Оркестратор: обов'язки і структура

Функції:
  • Відстеження стану саги: `PENDING → RUNNING → COMPENSATING → DONE/FAILED`.
  • Планування кроків, дедлайни, таймаути, ретраї.
  • Роутинг подій і запуск компенсацій.
  • Ідемпотентність операцій координатора (журнал команд).
  • Спостережуваність: кореляція'saga _ id'в логах/трейсах/метриках.
Зберігання:
  • Таблиці'saga','saga _ step','commands','outbox'.
  • Індекси по'saga _ id','business _ key','status','next _ run _ at'.

8) Хореографія: правила і захист від «снігового кома»

Контракти подій: схеми та версіонування (Avro/Proto/JSON Schema).
Чітка семантика: «подія факту» vs «команда».
Останів ланцюжка: сервіс, виявивши невідповідність, публікує «Failed »/« Compensate» подію.
Сигналізація і алерти на «нескінченні петлі».


9) TCC: Практичні деталі

Try: резерв ресурсу з TTL.
Confirm: фіксація, звільнення тимчасових блокувань.
Cancel: відкат резерву (без побічних ефектів).
Гарbage collection: автоматичний відмін Try після TTL (ідемпотентний Cancel).
Ідемпотентні Confirm/Cancel: повтор безпечний.


10) Приклад (словесна схема) - «Замовлення з оплатою і доставкою»

1. CreateOrder (локально) → outbox: `OrderCreated`.
2. PaymentService: резерв «Try» (TCC); при успіху →'PaymentReserved', при відмові →'PaymentFailed'.
3. InventoryService: резерв товару; при нестачі →'InventoryFailed'.
4. ShippingService: створення слоту доставки (скасовується).
5. Якщо будь-який крок'Failed'→ оркестратор запускає компенсації в зворотному порядку: `CancelShipping` → `ReleaseInventory` → `PaymentCancel`.
6. Якщо все ок →'PaymentConfirm'→'OrderConfirmed'.


11) Псевдокод оркестратора

pseudo startSaga(saga_id, order_id):
steps = [ReservePayment, ReserveInventory, BookShipment, ConfirmPayment]
for step in steps:
res = execWithRetry(step, order_id)
if!res.ok:
compensateInReverse(steps_done(order_id))
return FAIL return OK

execWithRetry(step, key):
for attempt in 1..MAX:
try:
return step.run(key)    # идемпотентно catch RetryableError:
sleep(backoff(attempt))
catch NonRetryableError:
return FAIL return FAIL

compensateInReverse(done_steps):
for step in reverse(done_steps):
step.compensate()       # идемпотентно

12) Спостережуваність та операційні SLO

Трейсинг: єдиний'saga _ id', анотації'step','attempt','decision'( run/compensate/skip).

Метрики:
  • Успіх/помилка саг (%), середня тривалість, p95/p99.
  • Частка компенсованих саг, топ причин компенсацій.
  • Черги/outbox лаги, ретраї по кроках.
  • Логи/аудит: рішення оркестратора, ідентифікатори ресурсів, бізнес-ключі.

13) Тестування і хаос

Ін'єкція помилок в кожен крок: таймаути, «5xx», бізнес-конфлікти.
Out-of-order події, дублікати, пропуски (drop).
Довгі хвости латентності → перевірка дедлайнів і компенсацій.
Масові саги → перевірка WFQ/DRR і caps в чергах, відсутність «head-of-line blocking».
Редрайв з DLQ по кроках і по цілій сазі.


14) Мульти-тенантність, регіони, відповідність

Теги'tenant _ id/plan/region'в подіях і сховищах саг.
Residency: дані/події не залишають регіон; крос-регіональні саги проектуйте як федерації локальних саг + агрегуючі події.
Пріоритизація: VIP-саги мають більшу квотну вагу; ізоляція воркерів per tenant.


15) Чек-лист перед продом

  • У кожного кроку є чіткий компенсатор, обидва - ідемпотентні.
  • Обрано шаблон: оркестрація/хореографія/ТСС; описані межі відповідальності.
  • Outbox/Inbox впроваджені, дедуплікація по'operation _ id'.
  • Політики ретраїв: backoff з джитером, ліміти спроб і загальний дедлайн саги.
  • Контракти подій версіоновані, є валідація схеми.
  • DLQ і безпечний редрайв налаштовані.
  • Телеметрія: метрики, трейсинг, кореляція'saga _ id'.
  • Операційні playbooks: ручний cancel/force-confirm, розшивка «завислих» саг.
  • Тести хаосу і навантаження проходять, SLO/бюджет помилок визначені.

16) Типові помилки

Немає компенсатора або він «нечистий» (має побічні ефекти).
Відсутня ідемпотентність/дедуп - дублі і «гойдалки» станів.
«Сага в сазі» без явних кордонів - цикли і взаємні блокування.
Немає дедлайнів → «вічні» саги і витоки ресурсів.
Оркестратор зберігає стан «в пам'яті» без стійкого стору.
Хореографія без центру телеметрії → «невидимі» збої.
Непрозорий UX: користувачі не бачать проміжних статусів.


17) Швидкі рецепти

Класика SaaS: оркестрація + outbox/inbox, експоненціальний backoff, DLQ, статуси саги в UI.
Сильні інваріанти на ресурс: TCC з TTL резерву і GC Cancel.
Високий обсяг/навантаження: хореографія подій + сувора ідемпотентність і метрики за ключем.
Мульти-регіон: локальні саги + фінальні агрегати; уникати глобальних блокувань.


Висновок

Саги - це спосіб отримати передбачувану узгодженість в розподілених системах без глобальних блокувань. Чіткі компенсатори, ідемпотентність, надійна доставка (outbox/inbox), дисципліна таймаутів і ретраїв, плюс телеметрія і плейбуки - ключ до того, щоб складні бізнес-процеси залишалися стійкими і читаємими при зростанні навантаження, числа сервісів і географій.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.