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

Почему хранилище событий должно быть на стороне записи?

Источники событий распределяются как бонус для нескольких вещей, например. истории событий/аудита, полной и последовательной регенерации просмотров и т.д. Звучит здорово. Я фанат. Но это детали реализации на стороне чтения, и вы можете сделать то же самое, переместив хранилище событий полностью на чтение в качестве другого абонента. Так почему бы и нет?

Вот некоторые мысли:

  • Представления/денормализаторы не заботятся о хранилище событий. Они просто обрабатывают события из домена.
  • Перемещение хранилища событий в сторону чтения по-прежнему дает вам историю событий/аудит
  • Вы все еще можете восстановить свои представления из хранилища событий. Кроме того, это не должно быть утечкой модели записи. Дайте ему образцовое гражданство!

Здесь, кажется, есть один технический аргумент для сохранения его на стороне записи. Это от Грега Янга на http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/:

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

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

И после того, как снимок сделан, события до моментального снимка становятся на 100% бесполезными с точки зрения записи, за исключением... для восстановления прочитанной стороны! Это кажется неправильным.

Еще одна тема, связанная с производительностью: хранилище файлов. Иногда нам приходится связывать большие двоичные файлы с сущностями. Понятно, что иногда они связаны с сущностями, но иногда они представляют собой сущности. Помещение их в хранилище событий означает, что вы должны физически загружать эти данные каждый раз при загрузке объекта. Это достаточно плохо, но представьте несколько или сотни из них в большой совокупности. Каждый ответ, который я видел, заключается в том, чтобы в основном укусить пулю и передать uri в файл. Это отмена и подрывает распределенную систему.

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

Разве не все точки CQRS, что случаи использования вокруг модели чтения и модели записи принципиально несовместимы? Итак, почему мы должны помещать читаемые элементы модели на стороне записи, жертвуя гибкостью и производительностью, и снова связываем их. Зачем тратить время?

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

Так может кто-нибудь, пожалуйста, объясните мне одну или несколько убедительных причин, чтобы сохранить ее на стороне записи? Или, альтернативно, почему это НЕ должно идти на стороне чтения в качестве беспокойства по обслуживанию/отчетности? Опять же, я не стану сомневаться в полезности магазина. Где он должен идти:)

4b9b3361

Ответ 1

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

Система, в которой ваши агрегаты хранят только моментальные снимки, но отправляет события в модель чтения для проектирования в считываемые модели, я бы назвал "CQRS", а не "Event Sourcing". Если вы сохранили события для повторной проекции, я думаю, у вас будет система, которая была бы очень и то и так.

Но разве у вас не было бы трех определений? Один для сохранения ваших агрегатов, один для обмена изменениями состояния и любого числа больше для ответа на запросы?

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

Ответ 2

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

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

Первая проблема, с которой вы столкнетесь, заключается в публикации ваших событий. Что происходит, когда я сохраняю базу данных и публикую ее в MSMQ (я умираю посередине). Таким образом, DTC вводится между ними. Это огромная вещь, которую нужно внести, распределенные транзакции следует избегать, как чума. Это также довольно неэффективно, поскольку я, вероятно, делаю данные долговечными дважды (один раз для очереди один раз в базу данных). Это значительно сократит пропускную способность системы (тесты DTC 200-300 сообщений в секунду являются общими, а событиями всего 20-30 к/сек являются обычными).

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

Что происходит, когда у вас есть ошибка? Я знаю, что вы никогда не будете писать багги-код, но один из разработчиков Jrs/maintenance позже будет работать с проектом. В качестве примера, что происходит, когда изменение объекта домена и поднятое событие не совпадают? Предположим, вы установили State на свой доменный объект на "LA" (hardcoded), но вы правильно настроили State на событие на cmd.State( "CT" ).

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

Ответ 3

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