вторник, 30 июня 2026 г.

Giga. CQRS, Command Query Responsibility Segregation

Giga. CQRS,  Command Query Responsibility Segregation

https://giga.chat/link/gcsoSWkiXV

Английское наименование: CQRS (Command Query Responsibility Segregation).

Русская трактовка: Это архитектурный паттерн, который разделяет ответственность за чтение данных (запросы, Queries) и запись данных (команды, Commands) на уровне всей системы. В отличие от CQS, который является принципом на уровне кода (методов), CQRS — это принцип на уровне архитектуры (сервисов, моделей, баз данных).

Детальное объяснение

Если CQS говорит нам: «Метод должен быть либо командой, либо запросом», то CQRS говорит: «Ваша система для чтения должна быть полностью отделена от вашей системы для записи».

В традиционной (CRUD) архитектуре у нас есть единая модель данных и единый API, который отвечает и за создание/обновление, и за чтение. Например, операция GET /users/5 и PUT /users/5 работают с одной и той же сущностью User.

CQRS предлагает разделить эти пути:

  1. Модель для записи (Command Model):

    • Назначение: Обработка команд (CreateOrder, UpdateCustomerAddress, CancelShipment).
    • Особенности: Эта модель оптимизирована для транзакционности и целостности данных. Она может быть представлена в виде богатой доменной модели (Domain Model), которая инкапсулирует сложную бизнес-логику. Структура базы данных для записи обычно нормализована, чтобы избежать аномалий при записи.
    • Результат: Успешное выполнение команды приводит к изменению состояния системы и, как правило, к публикации события (например, OrderCreated).
  2. Модель для чтения (Query Model):

    • Назначение: Обслуживание запросов (GetCustomerOrders, FindProductsByCategory, GetUserProfile).
    • Особенности: Эта модель оптимизирована для скорости чтения и простоты. Она часто представляет собой денормализованную или "плоскую" проекцию данных, собранную из разных источников. Вместо сложных JOIN-запросов к нормализованным таблицам, здесь используются простые и быстрые запросы к денормализованным представлениям (например, к материализованным представлениям в БД или к read-only репликам).
    • Результат: Запрос возвращает DTO (Data Transfer Object) с уже готовыми для отображения данными.

Как это работает вместе? (Роль Event Sourcing)

Часто CQRS идет рука об руку с другим паттерном — Event Sourcing (Событийное хранение).

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

Таким образом, модель для чтения является не источником истины, а производным представлением, которое асинхронно обновляется на основе событий из модели для записи.

Ключевые преимущества

  • Оптимизация производительности: Вы можете независимо масштабировать читающую и пишущую части системы. Для чтения можно создать множество реплик базы данных с денормализованными данными.
  • Гибкость: Вы можете использовать разные технологии для чтения и записи. Например, для записи использовать реляционную СУБД (PostgreSQL), а для чтения — быструю NoSQL базу (MongoDB) или аналитическую базу (ClickHouse).
  • Безопасность: Проще настроить права доступа. Вы можете дать доступ к модели для чтения широкому кругу пользователей, а доступ к модели для записи — только доверенным сервисам.
  • Простота моделей: Модель для записи может быть сложной и содержать всю бизнес-логику, в то время как модель для чтения будет состоять из простых объектов без какой-либо логики.

Недостатки

  • Сложность: Это значительное усложнение архитектуры. Вместо одной модели у вас теперь две.
  • Асинхронность и итоговая согласованность (Eventual Consistency): Данные в модели для чтения могут отставать от модели для записи. Сразу после создания заказа команда GetOrderById может вернуть ошибку "заказ не найден", так как событие еще не обработалось и не обновило модель для чтения. Это требует особого подхода со стороны UI/API.

Сравнение CQS и CQRS

ХарактеристикаCommand-Query Separation (CQS)Command Query Responsibility Segregation (CQRS)
УровеньПринцип проектирования (уровень методов)Архитектурный паттерн (уровень системы)
ЦельСделать код чище и предсказуемееОптимизировать производительность и масштабируемость
РазделениеРазделение ответственности внутри одного объектаРазделение ответственности на разные модели/подсистемы
СложностьНизкая. Легко применять в любом коде.Высокая. Требует серьезных изменений в архитектуре.

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

Комментариев нет:

Отправить комментарий