Базы данных

Распределённые транзакции: 2PC и альтернативы

Booking.com. Пользователь бронирует отель и авиабилет одновременно. Payment сервис списал деньги. Hotel сервис недоступен. Деньги ушли, отель не забронирован. Это не баг - это фундаментальная проблема распределённых транзакций. Решения существуют - от 2PC до Saga, каждое с ценой.

  • Uber использует Cadence (предшественник Temporal) для Saga-orchestration поездок: charge, dispatch, trip, payout - каждый шаг с компенсацией. 100M+ workflow executions в день
  • Google Spanner обслуживает Google Ads, Google F1 (YouTube), Google Cloud SQL - глобально consistent транзакции через TrueTime + Paxos. 99.999% availability
  • Stripe использует idempotency keys + outbox pattern вместо distributed transactions - каждая операция идемпотентна, at-least-once delivery через Kafka

2PC: координация через две фазы

Two-Phase Commit (2PC) - протокол 1978 года, Jim Gray. Цель: атомарная запись в несколько баз данных. Либо все commit, либо все rollback. XA-стандарт (X/Open Distributed Transaction Processing) стандартизировал интерфейс. Java JTA реализует поверх XA.

Проблема 2PC: coordinator является single point of failure. Если coordinator падает после отправки PREPARE но до COMMIT - участники заблокированы indefinitely. Они залоггировали PREPARE (нельзя commit самостоятельно), ресурсы заморожены. Это называется in-doubt transaction. Промышленные СУБД хранят in-doubt transactions до прихода нового coordinator.

In-doubt transactions в PostgreSQL видны в pg_prepared_xacts. Они держат row locks - блокируют обычные транзакции. Если coordinator падёт навсегда, нужно ручное вмешательство DBA: COMMIT PREPARED или ROLLBACK PREPARED. Это один из главных аргументов против 2PC в microservices: operational nightmare при сбоях.

Что происходит если coordinator падает между фазой PREPARE и COMMIT?

3PC: попытка решить blocking проблему

Three-Phase Commit (3PC) добавляет промежуточную фазу PRE-COMMIT между PREPARE и COMMIT. Цель: устранить blocking failure mode 2PC. Если coordinator упал - участники могут самостоятельно принять решение на основе знания о состоянии других участников.

Проблема 3PC: неустойчив при сетевых партициях. Network partition в момент PreCommit: часть участников получила PreCommit, часть нет. Одна группа решает commit, другая abort. Violated atomicity! 3PC безопасен только в синхронной сети без partitions - нереалистичное предположение для распределённых систем.

Paxos Commit (Gray & Lamport, 2004) - формальное решение: вместо coordinator используется Paxos quorum. Каждая фаза голосования через Paxos. Если 'coordinator' упал - любой участник может инициировать Paxos round. Google Spanner использует именно этот подход через Paxos groups. Latency выше: 2-3 round trips вместо 2.

Почему 3PC не решает проблему 2PC при сетевых партициях?

Saga: eventual consistency вместо ACID

Saga Pattern (Garcia-Molina & Salem, 1987) - отказ от distributed ACID в пользу eventual consistency с компенсирующими транзакциями. Вместо одной атомарной транзакции - последовательность локальных транзакций, каждая с компенсационной транзакцией для отката.

Choreography vs Orchestration. Choreography: каждый сервис публикует событие, следующий реагирует (Kafka events). Нет центрального координатора. Сложно отследить flow. Orchestration: центральный Saga Orchestrator (отдельный сервис или Temporal Workflow) вызывает каждый шаг, обрабатывает ошибки. Проще наблюдать, проще debug.

Temporal.io - Saga orchestration platform. Workflows - это durable functions: при crash автоматически восстанавливаются с последнего checkpoint через event sourcing. Uber использует Temporal для 100M+ workflow executions в день. Cadence (предшественник Temporal) обрабатывает поездки Uber.

Главное отличие Saga от 2PC?

Google Spanner и Paxos Commit

Google Spanner (2012): первая система с external consistency в глобальном масштабе. TrueTime API - синхронизация через GPS и атомные часы с погрешностью < 7мс. Транзакции commit timestamp присваивается после ожидания 2*epsilon для гарантии ordering.

Spanner использует Paxos groups вместо 2PC coordinator. Каждый shard - Paxos group из 5 реплик. Транзакция через несколько shards: leader каждого shard участвует в 2PC-подобном протоколе, но failure coordinator (leader) прозрачно обрабатывается через Paxos leader election. Blocking period = Paxos election timeout (~100ms).

CockroachDB и YugabyteDB реализуют схожий подход без GPS. Вместо TrueTime - HLC (Hybrid Logical Clocks). Немного слабее гарантии (linearizability vs external consistency), но без специального железа. CockroachDB используется в DoorDash, Netflix для глобально распределённых транзакций.

Какую проблему 2PC решает Paxos Commit?

Выбор протокола: pragmatic guide

Выбор между 2PC, Saga и Paxos Commit определяется тремя факторами: consistency требования, latency бюджет, операционная сложность. Нет universal answer - только tradeoffs.

Практическое правило 2024: избегай 2PC в microservices. Saga (Choreography или Temporal) - для большинства inter-service транзакций. 2PC допустим внутри одного кластера PostgreSQL с pg_prepared_xacts (XA). Paxos/Raft-based (CockroachDB, Spanner) - если нужна global ACID и есть бюджет.

Outbox Pattern - надёжный способ интеграции Saga с event-driven: INSERT в orders таблицу + INSERT в outbox таблицу в одной локальной транзакции. Отдельный поллер читает outbox и публикует события. Guarantees at-least-once delivery без distributed transaction. Debezium (Kafka Connect) реализует это через CDC из outbox.

Распределённые транзакции можно реализовать надёжно через 2PC с хорошим мониторингом

2PC имеет фундаментальный blocking failure mode: coordinator crash = frozen participants до восстановления. Мониторинг помогает обнаружить, но не устраняет проблему

FLP impossibility (Fischer-Lynch-Paterson 1985) доказывает: в асинхронной сети с одним падающим процессом невозможен distributed consensus за конечное время. 2PC не является исключением. Paxos/Raft обходят это через вероятностные гарантии (quorum, timeouts). Saga обходит через relaxed consistency

Когда 2PC остаётся разумным выбором в 2024?

Связанные темы

Распределённые транзакции пересекают boundaries БД, messaging и consensus:

  • Блокировки и дедлоки — Локальные блокировки - фундамент для distributed
  • CAP-теорема — CAP определяет пространство возможных trade-offs
  • Saga Pattern в messaging — Choreography через event-driven messaging

Ключевые идеи

  • 2PC: coordinator = SPOF, blocking failure mode при crash. Работает внутри одного кластера
  • 3PC: non-blocking при fail-stop, но уязвим к network partitions - практически не используется
  • Saga: eventual consistency + compensating transactions. Choreography (events) или Orchestration (Temporal)
  • Paxos Commit (Spanner, CockroachDB): ACID без blocking через Paxos leader election

Вопросы для размышления

  • Как выбрать между Choreography Saga и Orchestration Saga для конкретного бизнес-процесса?
  • Что такое compensation idempotency и почему это критично для правильной Saga реализации?
  • Когда eventual consistency достаточна, а когда strong consistency обязательна - где провести границу?

Связанные уроки

  • db-15-locks — Блокировки - основа distributed координации
  • db-03-acid — ACID - цель распределённых транзакций
  • db-04-cap — CAP определяет ограничения распределённых транзакций
  • bt-18-saga — Saga pattern - основная альтернатива 2PC
  • dist-07-transactions
Распределённые транзакции: 2PC и альтернативы

0

1

Войти