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

Что такое паттерн SAGA?

2.2 Middle🔥 182 комментариев
#JavaScript Core

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

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

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

Что такое паттерн SAGA?

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

Проблема, которую решает SAGA

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

  • Низкой производительности (блокировки ресурсов).
  • Снижения доступности (отказ одного сервиса может заблокировать всю транзакцию).
  • Сложности интеграции с различными технологиями (например, SQL и NoSQL БД).

SAGA решает эту проблему, заменяя долгую ACID-транзакцию на цепочку независимых локальных транзакций, где каждая последующая транзакция инициируется событием от предыдущей.

Как работает SAGA?

Существует две основные модели реализации SAGA:

  1. Оркестрируемая (Orchestrated) SAGA
    В этой модели есть центральный компонент — оркестратор, который управляет потоком транзакций. Оркестратор отправляет команды сервисам, дожидается их ответов и решает, какой шаг выполнить дальше. Это напоминает workflow-движок.

    Пример кода (оркестратор на Node.js):

    class OrderSagaOrchestrator {
      async createOrder(orderData) {
        try {
          // Шаг 1: Создать заказ
          const order = await orderService.create(orderData);
          await this.executeStep('payment', order);
          
          // Шаг 2: Списать средства
          const payment = await paymentService.charge(order);
          await this.executeStep('inventory', order);
          
          // Шаг 3: Обновить инвентарь
          await inventoryService.reserveItems(order);
          await this.executeStep('notification', order);
          
          // Шаг 4: Уведомить пользователя
          await notificationService.sendConfirmation(order);
          return order;
        } catch (error) {
          await this.compensate(order); // Запуск компенсирующих транзакций
          throw error;
        }
      }
    }
    
  2. Хореографическая (Choreographed) SAGA
    Здесь нет центрального оркестратора. Каждый сервис прослушивает события от других сервисов и самостоятельно инициирует следующий шаг или компенсирующее действие. Сервисы взаимодействуют через шину событий.

    Пример потока событий:

    Сервис заказов → Событие "OrderCreated" → Сервис платежей
    Сервис платежей → Событие "PaymentCompleted" → Сервис инвентаря
    Сервис инвентаря → Событие "InventoryReserved" → Сервис уведомлений
    

Компенсирующие транзакции (Compensating Transactions)

Ключевой механизм SAGA — обеспечение согласованности через откат. Если какой-либо шаг цепочки завершается неудачей, система должна выполнить компенсирующие транзакции для каждого уже завершённого шага, чтобы откатить изменения. Например:

  • Для транзакции "списать средства" компенсацией будет "вернуть средства".
  • Для "забронировать товар" — "отменить бронь".

Это реализует модель Eventually Consistent — система в конечном итоге приходит в согласованное состояние, но возможны временные несоответствия.

Преимущества и недостатки

Преимущества:

  • Высокая доступность — сервисы не блокируют друг друга.
  • Масштабируемость — каждый сервис автономен.
  • Гибкость — поддержка разнородных технологий.
  • Устойчивость — сбои обрабатываются через компенсации.

Недостатки:

  • Сложность отладки — транзакция распределена по многим сервисам.
  • Риск циклических зависимостей в хореографическом подходе.
  • Требует тщательного проектирования компенсирующих действий.
  • Временная несогласованность данных (это trade-off).

Практическое применение

SAGA широко используется в сложных бизнес-процессах, таких как:

  • Обработка заказов в e-commerce (заказ → оплата → доставка).
  • Бронирование путешествий (билеты → отель → страховка).
  • Финансовые операции (переводы между счетами).

Пример сценария на TypeScript (хореография):

// Сервис заказов
class OrderService {
  async create(order: Order) {
    // Локальная транзакция
    await db.orders.insert(order);
    // Публикация события
    eventBus.publish('OrderCreated', { orderId: order.id, userId: order.userId });
  }
}

// Сервис платежей (подписчик на события)
class PaymentService {
  constructor() {
    eventBus.subscribe('OrderCreated', this.charge.bind(this));
  }
  
  async charge(event: OrderCreatedEvent) {
    try {
      await db.transaction(async () => {
        await chargeUser(event.userId, event.amount);
      });
      eventBus.publish('PaymentCompleted', { orderId: event.orderId });
    } catch (error) {
      eventBus.publish('PaymentFailed', { orderId: event.orderId });
    }
  }
}

Заключение

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