← Назад к вопросам

Какие знаешь способы координации транзакций в Saga?

3.0 Senior🔥 91 комментариев
#Базы данных#Брокеры сообщений#Микросервисы и архитектура

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Способы координации транзакций в Saga

В распределенных системах паттерн Saga используется для управления долгими транзакциями, состоящими из нескольких независимых шагов, каждый из которых может выполняться в отдельном сервисе или базе данных. Существуют два основных способа координации этих шагов: координация через события (Event-Driven / Choreography) и координация через оркестратор (Orchestration). Рассмотрим каждый подробно.

Координация через события (Choreography)

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

Принцип работы:

  1. Первый сервис начинает транзакцию и публикует событие о успешном выполнении своего шага.
  2. Следующий сервис подписан на это событие, выполняет свою локальную транзакцию и публикует своё событие.
  3. Если шаг завершился неудачно, сервис публикует событие об ошибке, которое может запустить компенсирующие транзакции (rollback) у предыдущих участников.

Пример кода (Choreography):

// Сервис A выполняет шаг и публикует событие
func ServiceAProcess() error {
    // Выполняем локальную транзакцию
    err := localTransactionA()
    if err != nil {
        publishEvent("StepAFailed", err)
        return err
    }
    publishEvent("StepACompleted", nil)
    return nil
}

// Сервис B слушает события от Сервиса A
func ServiceBListener(event Event) {
    switch event.Type {
    case "StepACompleted":
        err := localTransactionB()
        if err != nil {
            publishEvent("StepBFailed", err)
            // Сервис A должен запустить компенсацию
            publishEvent("CompensateA", nil)
        } else {
            publishEvent("StepBCompleted", nil)
        }
    case "CompensateB":
        compensateTransactionB()
    }
}

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

Недостатки: Сложность отслеживания состояния Saga, трудности в управлении компенсациями при большом числе участников, потенциальные циклические зависимости между сервисами.

Координация через оркестратор (Orchestration)

Это централизованный подход, где специальный компонент — оркестратор Saga — управляет выполнением всех шагов и компенсирующих транзакций по заранее определённому сценарию (workflow).

Принцип работы:

  1. Оркестратор получает команду начать Saga.
  2. Он последовательно вызывает каждый участник (сервис), ожидает результат и решает, продолжать или запускать компенсацию.
  3. Оркестратор хранит состояние Saga и обеспечивает детерминированность процесса.

Пример кода (Orchestration):

// Оркестратор Saga, управляющий сценарием
type SagaOrchestrator struct {
    steps []SagaStep
}

func (o *SagaOrchestrator) Execute(ctx context.Context) error {
    for i, step := range o.steps {
        err := step.Execute(ctx)
        if err != nil {
            // Выполняем компенсации для уже выполненных шагов
            for j := i - 1; j >= 0; j-- {
                o.steps[j].Compensate(ctx)
            }
            return err
        }
    }
    return nil
}

// Пример шага Saga
type SagaStep interface {
    Execute(ctx context.Context) error
    Compensate(ctx context.Context) error
}

// Конкретный шаг для Сервиса A
type ServiceAStep struct {
    client *ServiceAClient
}

func (s *ServiceAStep) Execute(ctx context.Context) error {
    return s.client.PerformTransaction(ctx)
}

func (s *ServiceAStep) Compensate(ctx context.Context) error {
    return s.client.RollbackTransaction(ctx)
}

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

Недостатки: Дополнительная точка отказа (оркестратор), необходимость поддерживать ещё один компонент, потенциальное снижение децентрализации системы.

Ключевые критерии выбора

При выборе способа координации в Go-проектах я учитываю:

  • Сложность бизнес-процесса: Оркестратор лучше для длинных, сложных, многошаговых Saga.
  • Уровень децентрализации: Choreography подходит для систем с сильной независимостью сервисов.
  • Инструменты: Для оркестратора часто используют Cadence, Temporal или собственные решения на основе Workflow Engine. Для Choreography — Kafka, RabbitMQ или NATS.
  • Требования к наблюдаемости: Оркестратор даёт более полное представление о состоянии Saga.

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

Какие знаешь способы координации транзакций в Saga? | PrepBro