Распределённые транзакции становятся болезненными там, где бизнес требует атомарности, а архитектура уже разделена на несколько сервисов и хранилищ.
В реальной инженерной работе эта глава помогает выбирать между двухфазной фиксацией, трёхфазной фиксацией, Saga и транзакционным журналом исходящих событий по границам домена, допустимым сбоям, блокировкам и цене координации.
В интервью и архитектурных разговорах она особенно полезна, когда нужно честно проговорить семантику тайм-аутов, частичную фиксацию, компенсации и требования к идемпотентности.
Практическая польза главы
Практика проектирования
Учит выбирать транзакционный паттерн по границам домена и допустимым сбоям.
Качество решений
Помогает сравнить двухфазную фиксацию, трёхфазную фиксацию и Saga через задержку, блокировки и операционную сложность.
Аргументация на интервью
Дает ясную схему объяснения координатора, участников, точки фиксации и пути восстановления.
Риски и компромиссы
Делает явными блокировки, частичную фиксацию, семантику тайм-аутов и требования к идемпотентности.
Контекст
Консистентность и идемпотентность
Распределённые транзакции — один из способов удержать согласованность, но не единственный.
нужна, когда важнее автономности отдельных сервисов. В таких сценариях важны , , , , и .
Перед выбором важно отделить от : это между атомарностью, доступностью и эксплуатационной ценой. На границах сервисов рядом часто появляется , чтобы сбой одного участника не забрал всю систему.
Цена проявляется при , , и . Поэтому рядом с протоколами фиксации часто проектируют , , , , , , и обработку .
Распределённые транзакции: двухфазная фиксация (2PC) и трёхфазная фиксация (3PC) нужны там, где бизнес-инвариант требует менять несколько независимых ресурсов как одно целое, а промежуточное состояние недопустимо. За эту атомарность платят задержками, блокировками и тем самым тяжёлым восстановлением после частичного отказа, ради которого протоколы и существуют.
Когда нужна распределённая транзакция
- Одна бизнес-операция должна атомарно изменить несколько независимых ресурсов или сервисов, и разнести её на отдельные шаги нельзя.
- Здесь не выдерживается даже временное расхождение состояния — промежуточный результат уже считается ошибкой.
- Если фиксация прошла частично, цена ошибки переходит в финансы, регуляторику или то, что видит пользователь.
Как работает двухфазная фиксация (2PC)
2PC: двухфазная фиксация
Prepare -> голоса участников -> общее решение COMMIT/ABORT
Координатор собирает голоса участников и принимает единое решение: зафиксировать или отменить всю транзакцию.
Сильные стороны
- Простая и понятная модель координации.
- Чётко отделяет фазу подготовки от финального решения.
Риски
- Блокировки при отказе координатора в неподходящий момент.
- Высокая чувствительность к настройкам тайм-аутов и повторов.
Шаги протокола
Текущая команда
Нажмите Старт, чтобы проиграть протокол по шагам.
Координатор
Ожидает запуск
Команд от координатора: 0
Участники
3 участника
Шаг: 0 / 8
Заказы
участник A
Ожидание команд
Участвовал в шагах: 0
Платежи
участник B
Ожидание команд
Участвовал в шагах: 0
Склад
участник C
Ожидание команд
Участвовал в шагах: 0
Как работает трёхфазная фиксация (3PC)
3PC: трёхфазная фиксация
CanCommit -> PreCommit -> DoCommit
Добавляет промежуточную фазу PreCommit, чтобы уменьшить риск блокировок при проблемах координатора.
Сильные стороны
- Снижает вероятность зависания в неопределённом состоянии.
- Явно разделяет намерение зафиксировать изменения и финальную команду.
Риски
- Больше сетевых раундов и более сложный конечный автомат.
- Требует очень аккуратной настройки тайм-аутов и восстановления.
Шаги протокола
Текущая команда
Нажмите Старт, чтобы проиграть протокол по шагам.
Координатор
Ожидает запуск
Команд от координатора: 0
Участники
3 участника
Шаг: 0 / 12
Заказы
участник A
Ожидание команд
Участвовал в шагах: 0
Платежи
участник B
Ожидание команд
Участвовал в шагах: 0
Склад
участник C
Ожидание команд
Участвовал в шагах: 0
Альтернатива
Event-Driven Architecture
Чаще, чем кажется, Saga и транзакционный журнал исходящих событий дают лучший баланс, чем глобальная фиксация: блокировок нет, а согласованность достигается шагами.
Компромиссы и альтернативы
Двухфазную фиксацию (2PC) проще объяснить и внедрить. Расплата приходит, когда координатор отказал после фазы подготовки: участники остаются заблокированными и держат ресурсы, пока он не вернётся.
Трёхфазная фиксация (3PC) убирает это зависание ценой ещё одного сетевого раунда — а вместе с ним растёт и конечный автомат протокола, который теперь надо корректно сопровождать.
Сетевые разделения, тайм-ауты и восстановление после частичных сбоев бьют по обоим протоколам одинаково: ошибка здесь не падает явно, а оставляет транзакцию в неопределённом состоянии.
В микросервисной архитектуре общая атомарная транзакция между сервисами почти всегда оказывается дороже и хрупче, чем кажется на схеме, — связность растёт, а отказ одного участника тормозит остальных.
Saga: оркестрация или хореография
Операция распадается на локальные шаги, каждый со своим компенсирующим действием. Атомарности нет — взамен исчезает глобальная блокировка и единая точка отказа в виде координатора.
Транзакционный журнал исходящих событий
Событие пишется в одной локальной транзакции вместе с бизнес-изменением, а публикует его позже отдельный воркер. Так уходит риск, что запись в базу и отправка сообщения разъедутся.
Идемпотентные команды и согласование состояния
Когда повтор команды безопасен, частичный сбой перестаёт быть катастрофой: систему добивает до согласованного состояния фоновая сверка, а не ручной разбор.
Пересмотр границ домена
Самый дешёвый способ обойтись без распределённой транзакции — чтобы её не было. Сдвиньте границы агрегатов так, чтобы инвариант жил внутри одного сервиса.
Практический чеклист
- Граница проведена явно: где действительно нужна атомарность, а где хватит согласованности в конечном итоге.
- У координатора есть стратегия восстановления и долговечный журнал — после перезапуска он знает, какие транзакции висят в неопределённом состоянии.
- Политики тайм-аутов проверены не на «основном сценарии», а на сетевых разделениях и задержках.
- Повторная команда фиксации или отмены не ломает участника — обработка идемпотентна.
- На спорный случай заложен бизнес-механизм компенсации и ручного разбора, а не только надежда на удачную автоматику.
Частая ошибка: вводить двухфазную фиксацию (2PC) между сервисами как «просто транзакцию», не посчитав заранее блокировки, модель повторов и цену восстановления, — и узнать о них уже в проде.
Источники
Связанные главы
- Консистентность и идемпотентность - Идемпотентность нужна, чтобы безопасно обрабатывать повторы и восстановление после сбоев.
- Event-Driven Architecture - Saga и асинхронная координация как практичная альтернатива общей распределённой транзакции по стандарту XA.
- Паттерны отказоустойчивости - Тайм-ауты, повторы и изоляция по отсекам определяют поведение транзакции при сбоях.
- Выбор лидера: паттерны и реализации - Координатор транзакции — это, по сути, лидер: его недоступность и переизбрание определяют, надолго ли зависнут участники.
- Тестирование распределённых систем - Частичную фиксацию, тайм-ауты и восстановление лучше воспроизвести и сломать в тестах — иначе их сценарий впервые отыграется в проде.
