Что такое протокол двухфазного коммита (2PC) в распределённых системах?

«Что такое протокол двухфазного коммита (2PC) в распределённых системах?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Фазы протокола:

  1. Фаза подготовки (Prepare)

    • Координатор отправляет всем участникам команду prepare.
    • Каждый участник выполняет локальные операции транзакции, блокирует ресурсы и записывает данные в лог, но не фиксирует.
    • Участник голосует: отправляет координатору YES (готов) или NO (не готов / ошибка).
  2. Фаза фиксации (Commit/Rollback)

    • Если все участники ответили YES: координатор отправляет команду commit. Участники фиксируют изменения и освобождают ресурсы.
    • Если хотя бы один участник ответил NO: координатор отправляет команду rollback. Все участники откатывают изменения.

Пример псевдокода:

// Координатор
boolean allPrepared = participants.stream()
                                  .allMatch(p -> p.prepare(transactionData));
if (allPrepared) {
    participants.forEach(p -> p.commit(transactionId));
} else {
    participants.forEach(p -> p.rollback(transactionId));
}

Ключевые проблемы 2PC:

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

Альтернативы: Для повышения доступности и производительности используют протоколы вроде трёхфазного коммита (3PC) или паттерн Saga (компенсирующие транзакции).