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) Чек-лист перед продом

  • У каждого шага есть четкий компенсатор, оба — идемпотентны.
  • Выбран шаблон: оркестрация/хореография/TCC; описаны границы ответственности.
  • 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).

Нажимая кнопку, вы соглашаетесь на обработку данных.