Как управлять изменениями ViewModel в CQRS + Event Sourcing Architecture - PullRequest
19 голосов
/ 07 апреля 2011

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

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

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

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

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

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

Ответы [ 4 ]

15 голосов
/ 08 апреля 2011

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

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

2 голосов
/ 07 апреля 2011

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

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

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

1 голос
/ 08 апреля 2011

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

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

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

0 голосов
/ 15 апреля 2011

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

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

...