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 предлагает разделить эти пути:
Модель для записи (Command Model):
- Назначение: Обработка команд (
CreateOrder,UpdateCustomerAddress,CancelShipment). - Особенности: Эта модель оптимизирована для транзакционности и целостности данных. Она может быть представлена в виде богатой доменной модели (Domain Model), которая инкапсулирует сложную бизнес-логику. Структура базы данных для записи обычно нормализована, чтобы избежать аномалий при записи.
- Результат: Успешное выполнение команды приводит к изменению состояния системы и, как правило, к публикации события (например,
OrderCreated).
- Назначение: Обработка команд (
Модель для чтения (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 мог бы означать наличие разных типов ячеек или разных конвейеров обработки: одни специализируются на обработке команд (изменение состояния), а другие — на обслуживании запросов (чтение состояния).
Комментариев нет:
Отправить комментарий