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

Ответ

Традиционные ACID-транзакции (например, двухфазный коммит) плохо подходят для микросервисов из-за сильной связанности и блокировок. Вместо них используются паттерны, основанные на принципе конечной согласованности (eventual consistency).

  1. Saga Pattern

    • Идея: Длинная транзакция разбивается на серию локальных транзакций в каждом сервисе. Если какой-то шаг не удается, выполняются компенсирующие транзакции для отмены предыдущих шагов.
    • Реализации:
      • Оркестрация (Orchestration): Центральный сервис-координатор управляет процессом, вызывая сервисы по очереди.
      • Хореография (Choreography): Сервисы общаются через события (events). Каждый сервис подписывается на события других и реагирует на них, запуская свою локальную транзакцию.
  2. Two-Phase Commit (2PC)

    • Идея: Классический алгоритм с координатором и участниками.
      • Фаза 1 (Prepare): Координатор спрашивает всех участников, готовы ли они к коммиту. Участники блокируют ресурсы.
      • Фаза 2 (Commit/Abort): Если все готовы, координатор отправляет команду commit. Если хоть один не готов — команду abort.
    • Недостатки: Считается анти-паттерном в микросервисах из-за низкой производительности, блокировок и наличия единой точки отказа (координатора).
  3. Outbox Pattern

    • Идея: Обеспечивает надежную доставку сообщений/событий. Вместо того чтобы сразу отправлять событие в брокер сообщений после изменения данных в БД, сервис выполняет 2 действия в рамках одной локальной транзакции:
      1. Сохраняет бизнес-сущность в свою таблицу.
      2. Сохраняет событие в специальную таблицу outbox.
    • Отдельный процесс (или сам сервис) асинхронно читает события из outbox и надежно доставляет их в брокер сообщений (Kafka, RabbitMQ). Это гарантирует, что событие не будет потеряно и будет отправлено только если бизнес-транзакция успешно завершилась.
  4. Event Sourcing

    • Идея: Состояние приложения не хранится в его текущем виде. Вместо этого хранится полная последовательность событий (фактов), которые привели к этому состоянию. Текущее состояние можно восстановить, "проиграв" все события. Этот подход хорошо сочетается с хореографической сагой.

Вывод: Для большинства микросервисных систем Saga и Outbox Pattern являются наиболее предпочтительными и популярными решениями. В Go для реализации саг часто используют готовые фреймворки, например, dtm-labs/dtm.