Подтвердить что ты не робот

Как управлять изменениями ViewModel в CQRS + Event Sourcing Architecture

В настоящее время мы оцениваем архитектуры CQRS и Event Sourcing. Я пытаюсь понять, что подразумевается при использовании такого дизайна. Два вопроса, на которые я пытаюсь найти ответы, следующие:

1) Что произойдет, если после того, как приложение было запущено и работает какое-то время, есть новое требование добавить дополнительное поле в ViewModel в базе данных ReadModel? Скажем, почтовый индекс клиента требуется на ViewModel CustomerList, где он не был ранее. Таким образом, дополнительный столбец можно легко добавить в базу данных ViewModel, но как это заполняется? Насколько я вижу, единственный способ - очистить базу данных чтения и воспроизвести все события с нуля, чтобы создать резервную копию базы данных ReadModel. Но что, если приложение работает и работает в течение нескольких месяцев или лет (как мы надеемся, это произойдет). Это может быть миллионы событий для воспроизведения, просто для добавления данных для столбца zipcode.

У меня такая же проблема, если по какой-либо технической причине база данных ReadModel не синхронизирована или мы хотим добавить новую базу данных ReadModel. Похоже, чем старше приложение, и чем больше оно используется, тем сложнее и дороже это получить обновленную версию readmodel. Или я где-то упускаю трюк? Что-то вроде моментальных снимков ReadModel?

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

Мне было бы интересно услышать от тех, кто некоторое время работал с такой системой, как разработали пути обслуживания и обновления.

Спасибо за любое время и ввод.

4b9b3361

Ответ 1

Красота использования источников событий с CQRS - это способность уничтожить прочитанную модель и перестроить ее с нуля, как уже упоминалось. По какой-то причине у людей есть такая идея, что это займет много времени после того, как вы преодолеете какое-то количество событий. Если вы используете реляционную базу данных для своих моделей чтения, и вы, скорее всего, можете открыть транзакцию, прочитать все события через обработчики и затем совершить транзакцию. Это происходит только тогда, когда транзакция совершает то, что мы на самом деле касаемся диска. Все остальное выполняется в памяти, чтобы оно было молниеносно. На самом деле, я бы не удивился, увидев, что ваша система прокручивается через несколько миллионов событий всего за несколько минут, если это произойдет.

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

Если вы столкнулись с ошибками, вы можете легко отлаживать потоковое/копирование производственных событий на локальную рабочую станцию, установку контрольных точек в ваших обработчиках и последующее выполнение этих событий с помощью кода обработки прочитанной модели.

Ответ 2

Я немного новичок в CQRS, поэтому это может быть не самый подходящий маршрут (но iirc я взял его из одного из списков рассылки CQRS/DDDD).

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

В обработчике мы используем любой механизм, который удобен, поэтому в случае добавления поля zip-кода мы можем запустить одноразовый запрос, который в этот момент вытаскивает почтовые коды из другой модели представления и заполняет новый столбец. Мы не беспокоимся об архитектурной чистоте в этих сценариях, так как ожидается, что это будет одноразовая операция (Rob Conery Massive используется с успехом в этих ситуациях).

Ответ 3

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

1) Read Model rebuild. Да, вы в основном должны перестроить всю Read Model DB, как только что-то в ней изменится. И если есть много событий, это может занять много времени. Таким образом, восстановление Read Model должно быть сильно оптимизировано (использование пакетной обработки событий и т.д.). Я чувствую, что поиск событий подходит лучше всего в тех случаях, когда есть высокий коэффициент чтения-записи. Поэтому для некоторых крайне волатильных данных может быть разумно не хранить его как события домена. Но тогда вопрос о пропускной способности также не так уж далек. В любом случае вы можете применить cqrs только к части системы, к которой лучше всего подходит (например, я, вероятно, не буду хранить графическое изображение как часть события).

2) Debugging. Очень маловероятно, что при хранении событий есть ошибка (это должно быть проблемой для структуры), и всегда легко проверить, какие события находятся в хранилище. Что касается команды для создания ожидаемых событий, у вас должны быть тесты здесь, и эти тесты, вероятно, будут самыми ценными тестами в системе. Для денормализаторов у вас также могут быть тесты, но я бы не стал писать тесты для тривиальных денормализаторов, если их правоту можно увидеть невооруженным глазом. При этом я несколько раз использовал отладчик, чтобы найти проблемы в некоторых более сложных денормализаторах; это было не так весело, пытаясь определить, какое событие заставляет все пойти не так.

Ответ 4

Также можно добавить событие netting в вашей модели. Это можно запустить как произвольную задачу после того, как X число событий было получено (скажем 500)

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