Что такое паттерн саги для распределенных транзакций
Что проверяют
Понимаете ли вы, что распределённой транзакции в микросервисах нет, и знаете ли, чем её заменяют.
Как отвечать
В монолите операция из нескольких шагов защищена транзакцией базы. В микросервисах у каждого своя база, общей транзакции нет, а двухфазный коммит на практике не применяют: он блокирует ресурсы и плохо переживает отказы.
Сага это последовательность локальных транзакций, где каждая публикует событие о своём результате, а на неудачу выполняются компенсирующие действия, отменяющие уже сделанное. Не откат, а обратная операция: не «отменить списание», а «сделать возврат».
Два способа управления:
- хореография: сервисы слушают события друг друга и реагируют. Проще, нет центральной точки, но общий процесс нигде не описан и его тяжело понять целиком;
- оркестрация: отдельный координатор вызывает шаги и знает состояние саги. Логика в одном месте, зато появляется компонент, который надо поддерживать.
Что обязательно назвать как требования: обработчики идемпотентны, потому что доставка «хотя бы один раз»; каждый шаг имеет компенсацию, а некоторые компенсировать нельзя (письмо уже отправлено), и это учитывают порядком шагов; состояние саги хранится, иначе после перезапуска непонятно, где остановились; согласованность здесь в конечном счёте, и промежуточные состояния видны пользователю.
Полезно упомянуть Transactional Outbox: событие и изменение данных пишутся в одной локальной транзакции, иначе возможна ситуация «данные сохранились, событие не ушло».
Где спотыкаются
Предлагают двухфазный коммит как рабочее решение.
Не продумывают компенсации и получают систему, которая умеет только успешный сценарий.
Забывают про идемпотентность и повторную доставку.
Публикуют событие отдельно от записи в базу и теряют его при сбое.