Найти в Дзене
Системный Пазл

CQRS и Saga: Подробный разбор паттернов для микросервисов

Оглавление

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

CQRS (Command Query Responsibility Segregation)

Что это?

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

Зачем нужно?

  • Масштабируемость: Чтение (например, отчеты) и запись (например, оплата) могут масштабироваться независимо.
  • Гибкость: Разные модели для разных задач (оптимизация под аналитику или транзакции).
  • Производительность: Кэширование данных для чтения без влияния на запись.

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

  1. Command Side (Запись):
  2. Принимает команды (CreateOrder, UpdateUser).
  3. Валидирует данные и обновляет Write Model (основная БД).
  4. Публикует события об изменениях (например, через Kafka).
  5. Query Side (Чтение):
  6. Слушает события из Command Side.
  7. Обновляет Read Model (оптимизированную для чтения, например, денормализованную таблицу).
  8. Отвечает на запросы (GetOrderDetails, GetUserStatistics).

Пример:

  • В интернет-магазине:
  • Command: Создание заказа → пишет в PostgreSQL.
  • Query: Отображение истории заказов → читает из ElasticSearch (быстрый поиск).

Плюсы:

  • Разделение нагрузки.
  • Возможность использовать разные СУБД (PostgreSQL для записи, Redis для чтения).

Минусы:

  • Сложность синхронизации данных между Write и Read моделями.
  • Риск «несвежих» данных в Read Model.

Saga

-2

Что это?

Паттерн для управления распределенными транзакциями в микросервисах. Гарантирует согласованность данных между сервисами без использования ACID-транзакций (которые невозможны в распределенных системах).

Зачем нужно?

В микросервисах:

  • Нет единой БД → транзакции охватывают несколько сервисов.
  • Нужен механизм отката изменений при ошибках.

Типы Saga:

1. Choreography (Хореография)

Каждый сервис самостоятельно запускает следующие шаги и обрабатывает ошибки через события.

Как работает:

Сервис А выполняет действие → публикует событие.

Сервис Б слушает событие → выполняет свое действие → публикует новое событие.

Если ошибка → сервис публикует событие-компенсацию.

Пример Saga для заказа:

CopyOrderService → Создает заказ → публикует «OrderCreated».

InventoryService → Резервирует товар → публикует «InventoryReserved».

PaymentService → Списание денег → публикует «PaymentCompleted».

Если оплата не прошла → PaymentService публикует «PaymentFailed» → OrderService отменяет заказ.

Плюсы:

Нет централизованного управления.

Высокая гибкость.

Минусы:

Сложно отслеживать поток событий.

Риск циклических зависимостей.

2. Orchestration (Оркестрация)

Центральный координатор (оркестратор) управляет потоком выполнения.

Как работает:

Оркестратор вызывает сервисы по очереди.

Если шаг завершен → переход к следующему.

Если ошибка → запускает компенсирующие транзакции.

Пример Saga с оркестратором:

1. Вызвать OrderService → создать заказ.

2. Если успешно → вызвать InventoryService → зарезервировать товар.

3. Если успешно → вызвать PaymentService → списать деньги.

4. Если оплата успешна → подтвердить заказ.

Если на любом шаге ошибка → откатить предыдущие шаги.

Плюсы:

Централизованное управление → проще дебажить.

Четкий контроль потока.

Минусы:

Оркестратор становится точкой отказа.

Дополнительная сложность реализации.

Когда использовать CQRS и Saga?

CQRS: Системы с высокой нагрузкой на чтение (аналитика, отчеты), где данные для чтения и записи имеют разную структуру.

Saga: Транзакции, затрагивающие несколько сервисов (например, оформление заказа, бронирование билетов).

Проблемы и решения

Для CQRS:

  • Синхронизация моделей: Используйте Event Sourcing (сохранение всех событий изменения состояния) + Kafka.
  • Задержка данных: Настройте TTL для кэша или информируйте пользователей о возможной задержке.

Для Saga:

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

Примеры реализации

CQRS + Event Sourcing

1. Пользователь отправляет команду "CreateUser".

2. Command Handler валидирует данные и сохраняет событие "UserCreated" в Event Store.

3. Read Model обновляется асинхронно (проекция события в MongoDB).

4. API для чтения возвращает данные из Read Model.

Saga с компенсацией

Сценарий: Отмена заказа.

1. OrderService → отменить заказ.

2. InventoryService → вернуть товар на склад.

3. PaymentService → вернуть деньги.

Если шаг 2 или 3 не выполнен → повторить компенсацию или уведомить поддержку.

🔥 Заключение

  • CQRS — ваш выбор, когда нужно разделить нагрузку и оптимизировать чтение/запись.
  • Saga — спасение для распределенных транзакций, но требует тщательного проектирования откатов.

Используете эти паттерны? Делитесь кейсами в комментариях!

#микросервисы #архитектура #CQRS #Saga