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

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

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

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

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

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

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

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

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

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

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

Предположим, операция изменяет данные в двух сервисах, и промежуточное состояние недопустимо. Если каждый сервис подтвердит свою локальную транзакцию независимо, возможен частичный успех: один участник зафиксировал изменения, второй — нет.

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

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

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

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

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

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

Поэтому нужно оценить:

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

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

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

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

Сервис оформления заказа должен создать заказ и одновременно уменьшить доступный остаток товара. Команда рассмотрела три варианта.

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

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

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

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

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

  1. Вопрос: Делает ли двухфазный коммит систему полностью устойчивой к сетевым сбоям?

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

  2. Вопрос: Почему увеличение числа участников ухудшает практические свойства двухфазного коммита?

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

  3. Вопрос: В чём принципиальная разница между откатом в распределённой транзакции и компенсацией в саге?

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