← Назад к списку
Системный дизайнАрхитектура и алгоритмыSenior

В микросервисной архитектуре заказ затрагивает сервисы оплаты, склада и доставки. Как обеспечить согласованность без распределённых транзакций? Расскажите про saga и transactional outbox.

Короткий ответ

  • 2PC в микросервисах не используют: блокировки и хрупкость
  • Saga — цепочка локальных транзакций с компенсациями при сбое
  • Хореография через события или оркестрация центральным координатором
  • Компенсация — бизнес-отмена, а не rollback базы
  • Outbox: событие пишется в ту же локальную транзакцию, что и данные
  • Релей публикует события из outbox в брокер — ничего не теряется
  • Потребители идемпотентны: доставка at-least-once даёт дубли

Saga разбивает бизнес-процесс на локальные транзакции с компенсациями, а outbox гарантирует, что изменение данных и публикация события происходят атомарно.

Как сказать вслух

пример ответа

Я объясню, почему двухфазный коммит здесь не вариант, и предложу сагу: каждый сервис делает свою локальную транзакцию и публикует событие, а при сбое выполняются компенсации в обратном порядке. Отдельно покажу проблему двойной записи — в базу и в брокер — и закрою её паттерном transactional outbox.

Подробный ответ

Основной ответ

Распределённая транзакция через 2PC держит блокировки на время координации и падает вместе с координатором, поэтому в микросервисах процесс оформляют сагой: заказ создан → оплата списана → товар зарезервирован → доставка назначена. Каждый шаг — локальная ACID-транзакция своего сервиса. При сбое шага выполняются компенсирующие действия в обратном порядке: вернуть деньги, снять резерв, отменить заказ. Координация — хореография (сервисы реагируют на события друг друга, просто, но процесс размазан) или оркестрация (отдельный компонент ведёт состояние саги — наглядно для длинных процессов). Публикация событий надёжна через outbox: сервис в одной транзакции пишет данные и строку события в таблицу outbox, затем релей (поллер или CDC типа Debezium) отправляет её в Kafka. Потребители дедуплицируют по id события.

Ключевые моменты

  • Компенсация — не rollback. Деньги уже списаны, письмо отправлено; компенсация — это новая бизнес-операция «возврат», и некоторые действия некомпенсируемы — их ставят последним шагом.
  • Хореография vs оркестрация. Хореография хороша для 2-3 шагов; при длинных процессах оркестратор даёт видимое состояние, таймауты и ретраи в одном месте.
  • Проблема двойной записи. Записать в БД и отдельно послать в брокер нельзя атомарно: между ними сервис может упасть; outbox сводит обе записи в одну локальную транзакцию.
  • Идемпотентные потребители. Релей гарантирует at-least-once, значит дубли неизбежны; потребитель хранит обработанные id событий или делает обработку естественно идемпотентной.

Практический контекст

Интервьюер смотрит, понимаете ли вы цену eventual consistency: статусы «в обработке» в UI, обработку частичных отказов, некомпенсируемые шаги. Полезно привязать к DDD: граница саги обычно совпадает с границами агрегатов и bounded context — внутри агрегата транзакция, между ними события. Уточните: сколько шагов в процессе, есть ли шаги без отмены, какой допустимый интервал рассинхронизации для бизнеса.

Частые ошибки

  • Предлагают двухфазный коммит между сервисами, игнорируя блокировки и отказ координатора
  • Пишут в базу и публикуют в Kafka двумя отдельными операциями — при падении между ними событие теряется
  • Считают компенсацию откатом транзакции и не продумывают некомпенсируемые шаги вроде отправленного email

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru