АрхитектураАрхитектура данныхАрхитектор распределённых систем

Сервис оформляет заказ через несколько автономных хранилищ. Как сага обеспечивает согласованность без общей...

Сервис оформляет заказ через несколько автономных хранилищ. Как сага обеспечивает согласованность без общей транзакции?

Проходите собеседования с ИИ помощником Hintsage

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

Сага разбивает бизнес-операцию на последовательность локальных транзакций, каждая из которых подтверждается независимо. Если следующий шаг не выполнен, система запускает компенсирующие действия для уже завершённых шагов, поэтому согласованность достигается не атомарностью, а управляемым переходом к согласованному состоянию.

Сага допускает временно видимые промежуточные состояния. Она не даёт тех же гарантий, что единая транзакция с атомарным коммитом, поэтому требует идемпотентности, надёжного хранения состояния процесса, повторов и контроля неуспешных компенсаций.

Исторический контекст

Распределённые бизнес-операции часто затрагивают несколько сервисов или хранилищ, которыми нельзя управлять одной локальной транзакцией. Попытка сделать единую транзакцию между ними приводит к необходимости координации, удержанию ресурсов и зависимости доступности всех участников.

Саги появились как подход к длительным распределённым операциям, где блокирующая атомарность слишком дорога или технически недоступна. Вместо единого отката всей операции система явно описывает действия, которые логически отменяют уже выполненные шаги.

Постановка проблемы

Например, оформление заказа может включать создание заказа, резервирование товара и списание или блокировку оплаты. Эти операции находятся в разных bounded context и могут завершаться с разной задержкой или временно быть недоступными.

Если после резервирования товара платёж не прошёл, простого отката локальной транзакции платежа недостаточно: резерв уже зафиксирован в другом хранилище. Без компенсации появится несогласованное состояние — заказ не оплачен, но товар недоступен для других покупателей.

Подробное решение

Сага представляет операцию как упорядоченный набор локальных шагов. Каждый участник выполняет свою транзакцию и сообщает результат; координатор или следующий участник инициирует дальнейший шаг. Для каждого необратимого на уровне бизнеса действия заранее определяется компенсирующее действие, например отмена резерва или возврат платежа.

Есть два распространённых стиля:

  • Хореография: участники реагируют на события друг друга. Она уменьшает роль центрального координатора, но усложняет понимание общего процесса и контроль зависимостей.
  • Оркестрация: отдельный координатор хранит состояние саги и отправляет команды участникам. Такой вариант лучше виден операционно, но координатор становится дополнительным компонентом и точкой развития логики процесса.

Компенсация не является техническим откатом. Она выполняется отдельной транзакцией и может быть отложенной, частично успешной или невозможной: например, уже отправленный товар нельзя буквально вернуть мгновенным откатом. Поэтому бизнес-процесс должен иметь состояния вроде ожидания, отмены, ручной проверки и завершённой компенсации.

Каждый шаг и каждая компенсация должны быть идемпотентными: повтор одной команды не должен повторно списать деньги или создать второй резерв. Состояние саги нужно надёжно сохранять, а сообщения — повторять после временных ошибок, отслеживая дубликаты, тайм-ауты и необрабатываемые события.

Сага обеспечивает eventual consistency, но не изоляцию между всеми шагами. Пользователи и другие процессы могут увидеть промежуточное состояние, поэтому модель данных и интерфейсы должны явно учитывать статусы операции. Для публикации переходов состояния также требуется надёжная связь локальной записи с отправкой события, иначе сама сага может потерять информацию о завершённом шаге.

Распределённая транзакция, например двухфазный коммит, может дать более сильную атомарность, но требует общего координатора и согласованного участия хранилищ. Это повышает связанность и чувствительность операции к сбоям и задержкам. Сага обычно предпочтительна для длительных бизнес-процессов, где локальная автономность важнее мгновенной атомарности.

Ситуация из практики

Интернет-магазин сначала создаёт заказ, затем резервирует товар на складе и запрашивает авторизацию платежа. Рассматривались два варианта: распределённая транзакция и сага. Распределённая транзакция дала бы единый результат, но потребовала бы участия склада, платёжного сервиса и базы заказов в общей координации; внешняя платёжная система при этом может не поддерживать нужный протокол.

Для саги выбрали оркестратор. После успешного создания заказа он запрашивает резерв, затем авторизацию платежа; при отказе платежа отправляет команду отмены резерва. Повторные команды идентифицируются ключом операции, а зависшие процессы попадают в очередь повторной обработки и на ручной разбор.

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

Что кандидаты часто упускают

  1. Достаточно ли компенсирующего действия, чтобы сага была эквивалентна откату транзакции?

Нет. Компенсация выполняет новую бизнес-операцию и может иметь собственные побочные эффекты. Возврат денег может быть отложен, отмена отправки — невозможна, а уведомление пользователя уже нельзя стереть. Поэтому сага должна моделировать реальные состояния и последствия, а не притворяться мгновенным откатом.

  1. Что произойдёт, если команда шага будет доставлена повторно?

Без идемпотентности возможны повторное списание, дублирование резерва или несколько созданных сущностей. Участник должен проверять уникальный идентификатор операции, хранить результат уже обработанной команды и безопасно возвращать тот же результат при повторе. Одной гарантии доставки недостаточно: повторы являются нормальной частью отказоустойчивой обработки.

  1. Как выбрать между хореографией и оркестрацией для длинного процесса?

Хореография подходит для небольшого числа слабосвязанных шагов, где правила переходов просты. При росте числа участников события начинают образовывать трудно обозримую сеть зависимостей, и диагностика становится сложнее. Оркестрация обычно предпочтительнее для длинных процессов с тайм-аутами, компенсациями и ручными решениями, хотя требует надёжного хранения состояния координатора и не должна превращаться в монолитную бизнес-логику всех сервисов.