2016-07-23 1 views
2

Я прочитал много статей о CQRS и одну маленькую вещь, которую я до сих пор не могу понять. Везде написано, что есть две модели (они могут иметь два разных типа хранилищ данных даже). Где одна модель называется write, а другая - read.Обновление части запроса в CQRS

Вот поток: например, модель записи вносит некоторые изменения, сохраняет эти изменения в (собственную) БД и запускает событие. Затем read модель, которая должна быть подписана на такое событие, обрабатывать ее и обновление собственной проекции это правильно? Если да, то это означает, что что-то, что люди называют моделью read, не читается только из хранилища.

Что мне не хватает? Главный вопрос заключается в том, какая часть отвечает за обновление проекции/части запроса?

P.S. Спасибо, ребята, за ваши ответы! Теперь головоломка собрана :-)

+1

Я бы сказал, что простые - как упоминалось в одном из ответов, эти термины - чтение и запись применимы только для публичных интерфейсов. Конечно, внутренние читают из модели записи и записывают в считываемую модель. Как правило, у вас есть агрегированные репозитории, которые читают и записывают модель записи и прогнозы, которые читают и записывают модель чтения. Сама суть каждого обновления в модели записи отправляется в проекции, которые затем могут обновлять прочитанную модель (написав ей!) –

ответ

2

Я так понимаю ...

команду/сторона записи является модель предметной области с ответственностью убедившись, что система находится в правильном состоянии - при использовании DDD то через агрегаты. Вы загружаете свой агрегат и применяете какое-то поведение. Это тот момент, когда ваши бизнес-правила и поведение живут. Здесь также вы будете поднимать события домена. Это хороший способ сделать это (особенно в сочетании с поиском событий, где ваша база данных - это ваших событий). Однако, Я не верю мандатам CQRS, используя события. Например, вы можете просто обновить некоторое состояние в базе данных sql. Командная часть предназначена для защиты инвариантов вашего домена,

Затем прочитайте модель, которая должна быть подписана на такое событие, обрабатывать ее и обновлять собственную проекцию, это правильно?

Если вы используете события, да. Но также см. Ниже ...

Если да, то это означает, что что-то, что люди называют моделью чтения, не читается только из хранилища.

Это зависит от вашего хранилища и того, как вы создаете свои прочитанные модели. Вы можете подписаться на события, затем обновить модели чтения в некоторой базе данных (могут быть таблицы в базе данных SQL, документы в базе данных документов) или в объектной модели в памяти. Затем вы запрашиваете эти модели чтения, загружая их из базы данных или модели в памяти.

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

Например, запрос API или веб-страницы приходит, вы выполняете запрос к своей базе данных, а затем возвращаете результаты пользователю. Этот запрос не проходит через модель домена. Вы все еще отделили свои чтения от своих записей, вы просто не использовали события.

Главный вопрос заключается в том, какая часть отвечает за обновление проекций/части запроса?

Если вы используете события, это будут подписчики событий. Вы будете слушать события, а затем обновлять свои модели. Фактическая реализация этих функций будет зависеть от вашей архитектуры. Например, при использовании EventStore клиент имеет встроенную поддержку концепции subscribers. Они могут быть реализованы в простом консольном приложении, например, или внутри API.

Поток для этого может идти, как:

  • App начинает
  • Подписка на N потоков событий
  • Когда вы получаете событие, обновление базы данных, или модель в памяти

Если вы не используете события, то это другое. Ваша архитектура может быть достаточно простой, чтобы сторона чтения просто запрашивала db (это уже актуально с командной стороны!).

+0

Возможно, это немного не по теме, но как вы реконструируете модель запроса на недавно добавленные 1 .. .N, развернутые дополнительно к активному кластеру. У меня есть 3 службы с актуальной моделью запроса с начала работы. Теперь я обнаруживаю большую нагрузку, поэтому я запускаю действие для развертывания дополнительных 10 экземпляров, каждый из которых имеет свою собственную локальную базу данных только для запросов. Как обновить эти базы данных со всеми запрошенными данными из прошлого, а не только с новыми событиями? – kensai

1

Если да, то это означает, в основном, то, что люди называют моделью чтения, которая не читает только.

В основном исправлены.

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

В середине есть процесс, который использует ограниченный интерфейс для считывания состояния модели записи, преобразует его из структуры данных, оптимизированной для записи, в оптимизированную структуру данных чтения, а затем использует ограниченный интерфейс для записи этого нового состояние считываемой модели.

Я думаю, что полезно ввести концепцию магазина, который отличается от модели. Модель записи вносит изменения в хранилище записи (например, книгу записи), а модель чтения использует состояние, опубликованное хранилищем чтения, для ответа на запросы, а ограниченные интерфейсы используются для связывания двух магазинов; это создает мост между моделью записи и моделью чтения.

Магазин в этом случае может быть только в памяти; Например, в java вы можете обновить хранилище чтения, обновив изменчивый дескриптор до оптимизированной для чтения структуры данных. Методы в модели данных просто захватывают самую последнюю доступную версию структуры данных и продолжают использовать эту копию до тех пор, пока запрос не будет завершен (гарантируя, что модель чтения создает результат запроса, который является внутренне согласованным).

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

Множество вариантов, но они имеют тенденцию следовать одному и тому же базовому шаблону.