Репортажи в мире CQRS/ES
Я думаю, что понимаю идею модели чтения в контексте ES + CQRS (пожалуйста, исправьте меня, если нет). Тем не менее, у меня все еще есть некоторые сомнения относительно использования его в контексте "серьезной" отчетности. Допустим, я использую реляционную базу данных плюс немного ORM для того, чтобы читать мои модели чтения. Одна базовая "модель чтения сводной статистики" может выглядеть так:
class SummaryStats1
{
public Guid TypeId { get; set; }
public string TypeName { get; set; }
public Guid SubTypeId { get; set; }
public string SubTypeName { get; set; }
public int Count { get; set; }
}
Учитывая событие:
TypeId = 3acf7d6f-4565-4672-985d-a748b7706a3e
TypeName = Bla1
SubTypeId = 41532aa1-f5d1-4ec4-896b-807ad66f75fc
SubTypeName = Bla2
Нормализатор будет:
(1) Проверьте, существует ли экземпляр вышеупомянутой комбинации (определенный с помощью TypeId, TypeName, SubTypeId, SubTypeName) (2) Если такого экземпляра нет, он создал бы экземпляр и установил Count равным единице. Если он есть, это увеличит количество на единицу.
Это приемлемый подход к отчетности? Я полагаю, что можно выполнить очень эффективные операции выбора для этой ненормализованной структуры данных (для фильтрации и других sql-проекций):
SELECT TypeName, Sum(Count) FROM SummaryStats1 GROUP BY TypeName
Согласятся ли с этим эксперты CQRS/ES? Является ли это "способом" ведения дел (т. Е. Созданием этих специальных моделей чтения отчетов)? Любые ссылки на исходный код / реальные примеры будут очень благодарны.
1 ответ
Это приемлемый подход к отчетности?
конечно, зависит ли это от способа доставки, в зависимости от ваших требований, но общая идея верна.
В итоге:
Вы генерируете свои модели чтения (иногда используется официальный термин Eager Read Derivation) на основе событий, поступающих с вашего домена.
Модели для чтения могут быть любыми (sql, redis, mongo и т. Д.). Все, что позволяет вашим запросам быть эффективными. Например, в вашем примере нет причины, по которой у вас не может быть двух моделей чтения для еще более эффективного выполнения ваших запросов (хотя того, что вы описываете, вполне достаточно для большинства случаев):
- ваш sql вид как описано
- предварительно агрегированное представление, сгруппированное по
typeName
чтобы вам не приходилось делать группу каждый раз по запросу (вместо этого вы вычисляете группировку в нормализаторе).
Короче говоря, нет правильного или неправильного способа построения моделей чтения. Прелесть в том, что вы абсолютно свободны в том, чтобы смоделировать модели, которые вы читаете, любым удобным для вас способом (исходя из представленных вами шаблонов запросов и узких мест производительности), не думая о том, как эти модели влияют на записи (просто потому, что они этого не делают. cqrs разбивает читает и пишет)
Использование событийного поиска в сочетании с CQRS дает еще более приятные возможности, а именно: создавать новые модели чтения и заполнять их данными, просто воспроизводя прошлые события из источника событий.
Просто несколько дополнительных примеров того, что можно считать "моделью чтения" ваших данных:
- представление INCR с Redis (альтернатива тому, что вы, казалось, описали)
- Elasticsearch / Solr поисковый индекс
- KV-магазин / индекс для быстрого поиска по ключу.
Идея еще раз заключается в том, что эти "модели чтения" / представления всегда обновляются (в конечном итоге согласованно) путем отправки на них событий обновления (обычно с помощью pubsub).
Для более хорошего прочтения смотрите ответ плюс ссылки на этот вопрос: Прочтите побочные подходы к реализации с использованием CQRS