Каковы недостатки использования Event Sourcing и CQRS?
Приобретение событий и CQRS отличное, потому что он заставляет разработчиков разработчиков застревать с одной предварительно смоделированной базой данных, с которой разработчик должен работать в течение всего срока службы приложения, если не существует большого проекта переноса данных. CQRS и ES также имеют другие преимущества, такие как масштабирование eventstore, журнал аудита и т.д., Которые уже находятся по всему Интернету.
Но каковы недостатки?
Вот некоторые недостатки, которые я могу придумать после изучения и написания небольших демонстрационных приложений
- Комплекс: Некоторые говорят, что ES сложна. Но я бы сказал, что сложное приложение лучше, чем сложная модель базы данных, на которой вы можете запускать очень ограниченные запросы с использованием языка запросов (несколько объединений, индексов и т.д.). Я имею в виду, что некоторые языки программирования, такие как Scala, имеют очень богатую библиотеку коллекций, которая очень гибкая, чтобы создавать некоторые серьёзные сложные агрегации, а также Apache Spark, которая упрощает сбор распределенных запросов. Но базы данных всегда будут ограничены возможностями языка запросов, а распределение баз данных сложнее, чем распределенный код приложения (просто разверните другой экземпляр на другой машине!).
- Использование большого дискового пространства. Хранилище событий может использовать много дискового пространства для хранения событий. Но мы можем запланировать очистку каждые несколько недель и создание моментального снимка, и, возможно, мы можем хранить исторические события локально на внешнем HD просто, если нам нужны старые события в будущем?
- Использование высокой памяти. Состояние каждого объекта домена хранится в памяти, что может увеличить использование ОЗУ, и все мы, как дорогостоящее ОЗУ. БОЛЬШАЯ ПРОБЛЕМА!!, потому что я беден! любое решение для этого? Может ли использовать Sqlite вместо сохранения состояния в памяти? Я делаю вещи более сложными, вводя несколько экземпляров Sqlite в моем приложении?
- Более длительное время загрузки. При сбое или обновлении программного обеспечения загрузка выполняется медленно в зависимости от количества событий. Но мы можем использовать моментальные снимки, чтобы решить эту проблему?
- Конечная согласованность: проблема для некоторых приложений. Представьте, что если Facebook использовал Историю источников событий с CQRS для хранения сообщений и учитывая, насколько загружена система facebook, и если бы я опубликовал сообщение, я бы увидела сообщение на fb на следующий день:)
- Сериализованные события в хранилище событий. События хранят события в виде сериализованных объектов, что означает, что мы не можем запрашивать содержимое событий в хранилище событий, которое в любом случае не рекомендуется. И мы не сможем добавить еще один атрибут события в будущем. Решение было бы хранить события как объекты JSON вместо сериализованных событий? Но это хорошая идея? Или добавить еще события для поддержки изменения объекта события orignal?
Может кто-нибудь прокомментировать недостатки, которые я здесь привел, и исправить меня, если я ошибаюсь, и предложить любые другие, которые я, возможно, пропустил?
Ответы
Ответ 1
Вот мой пример.
-
CQRS + ES может сделать вещи намного проще в сложных программных системах благодаря наличию богатых объектов домена, простых моделей данных, отслеживанию истории, большей видимости проблем, масштабируемости и т.д. concurrency. Это требует иного подхода к системам, поэтому трудно найти квалифицированных разработчиков. Но CQRS упрощает разделение обязанностей между разработчиками. Например, младший разработчик может работать исключительно со стороны чтения без необходимости касаться бизнес-логики.
-
Копии данных потребуют больше места на диске. Но в наши дни хранение относительно дешево. Может потребоваться, чтобы команда поддержки ИТ сделала больше резервных копий и планировала, как восстановить систему в случае, если что-то пойдет не так. Однако виртуализация серверов в наши дни делает его более упорядоченным рабочим процессом. Кроме того, гораздо проще создавать избыточность в системе без монолитной базы данных.
-
Я не считаю проблему с более высокой памятью проблемой. Гидратация бизнес-объектов должна производиться по требованию. Объекты не должны содержать ссылки на события, которые уже были сохранены. И гидратация событий должна произойти только при сохранении данных. На стороне чтения у вас нет конверсий Entity → DTO → ViewModel, которые обычно выполняются в многоуровневых системах, и вы не должны отслеживать изменения объектов, которые обычно выполняются полнофункциональными ORM. Большинство систем выполняют значительно больше чтений, чем записи.
-
Более длительное время загрузки может быть небольшой проблемой, если вы используете несколько гетерогенных баз данных из-за инициализации различных контекстов данных. Однако, если вы используете что-то простое, например ADO.NET, чтобы взаимодействовать с хранилищем событий и микро-ORM для чтения, система будет "холодным пуском" быстрее, чем любая полнофункциональная ORM. Здесь важна не слишком усложнять доступ к данным. На самом деле проблема CQRS должна решить. И, как я уже сказал, сторона чтения должна быть смоделирована для представлений и не иметь каких-либо накладных расходов на повторное сопоставление данных.
-
Двухфазная фиксация может хорошо работать для систем, которые не нужно масштабировать для тысяч пользователей в моем опыте. Вам нужно будет выбрать базы данных, которые будут хорошо работать с координатором распределенных транзакций. PostgreSQL может хорошо работать для чтения и записи отдельных моделей, например. Если система должна масштабироваться для большого количества одновременных пользователей, ее нужно будет спроектировать с возможной последовательностью. Бывают случаи, когда у вас будут сводные корни или границы контекста, которые не используют CQRS, чтобы избежать возможной последовательности. Это имеет смысл для несовместимых частей домена.
-
Вы можете запрашивать события в сериализованном формате, таком как JSON или XML, если вы выберете правильную базу данных для хранилища событий. И это должно быть сделано только для целей аналитики. Ничто внутри системы не должно запрашивать хранилище событий ничем иным, как идентификатором совокупного корня и типом события. Эти данные будут индексироваться и жить вне сериализованного события.
Ответ 2
Просто чтобы прокомментировать точку 5. Мне сказали, что Facebook использует ES с Eventual Consistency, поэтому вы можете иногда видеть, как сообщение исчезает и появляется после того, как вы его разместили.
Обычно модель чтения, к которой обращается ваш браузер, находится "близко" к вам, но после того, как вы сделаете сообщение, SPA переключится на модель чтения, близкую к вашей модели записи. Близкая близость между моделью записи (событиями) и моделью чтения означает, что вы можете увидеть свой собственный пост.
Однако через 15 минут ваш SPA переключится на первую, более близкую, читающую модель. Если событие, содержащее ваше сообщение, еще не распространилось на эту модель чтения, вы увидите, что ваш собственный пост исчезнет только для повторного появления позже.
Ответ 3
Я знаю, что прошло почти 3 года с тех пор, как этот вопрос был задан, но, тем не менее, эта статья может быть полезна для кого-то. Ключевые моменты
- Масштабирование со снимками
- Видимость данных
- Изменение схемы
- Работа со сложными доменами
- Нужно объяснить это большинству новых членов команды
Ответ 4
Источник событий и CQRS - это здорово, потому что он избавляет разработчиков от застревания с одной предварительно смоделированной базой данных, с которой разработчик должен работать на протяжении всего жизненного цикла приложения, если не существует проекта миграции больших данных.
Это большое заблуждение. Реляционные базы данных были придуманы именно для эволюции модели (благодаря простым двумерным таблицам в отличие от предварительно определенных иерархических структур). С представлениями и процедурами, обеспечивающими инкапсуляцию доступа к данным, логическая и физическая модель могут развиваться независимо. Именно поэтому SQL определяет DDL и DML на одном языке. Некоторые СУБД также позволяют создавать версии и развертывать все эти разработки в режиме онлайн (непрерывная доставка) в качестве переопределения на основе Oracle Edition.
Большие структуры данных предопределены и могут быть прочитаны только с кодом, разработанным для этой структуры. Хорошо, когда употребляется немедленно, но через 10 лет вам будет трудно прочитать его без точной версии, без языкового компилятора или интерпретатора.
Ответ 5
Надеюсь не опоздать на попытку дать ответ. За эти месяцы я провел много исследований по этому аргументу с целью реализации решения prduction-grade для некоторых частей моей архитектуры, где ES может иметь смысл
Сложный: На самом деле, он не должен быть сложным, его миссия - быть смертельно простой. Как? продвигая всю сложность от кода бизнес-логики до кода инфраструктуры. Доступ к данным должен осуществляться структурами, которые еще недостаточно развиты. Тем не менее, в гонке ES/CQRS нет явного победителя, возможно, потому, что по-прежнему используется нишевый/хипстерский подход (?). Поэтому некоторые команды внедряют свое собственное решение или внедряют некоторые готовые технологии, такие как Axon.
Высокое использование дискового пространства: я бы сказал больше, я бы сказал * потенциально бесконечный * Использование диска. Но если вы идете в сторону ES, у вас также есть очень веская причина, чтобы терпеть этот очевидный мусор. Давайте приведем некоторые из них:
-
Журналы аудита: хранилище данных - это журнал событий, мы его уже знаем. Финансовым приложениям или каждой критически важной миссии/безопасности может потребоваться централизованный журнал аудита, который позволяет указать, кто что сделал в какой момент. ES предоставляет эту возможность коробки... вы также можете украсить свои записи о событиях некоторыми бизнес-метаданными (например, идентификатор транзакции, связанный с некоторой идентификацией потребителя API, уровень серьезности операции...)
-
Высокий параллелизм: существуют системы, в которых логические состояния ресурсов изменяются многими клиентами одновременно. Это игры, платформы IoT и так далее. Ведение журнала событий вместо изменения представления состояния может быть разумным способом предоставления общего порядка событий. Другой способ состоит в том, чтобы делегировать в БД материал синхронизации. Но это не то, что вы хотите, если вы в ES
-
Аналитика Допустим, у вас есть много данных с большой коммерческой ценностью, но вы все еще не знаете, какие именно. В течение многих лет мы извлекали знания из информации приложений, переводя организацию данных с различными информационными моделями (кубами OLAP). Магазин событий снова предоставляет нечто подобное из коробки. Журнал событий - это самая грубая форма представления информации. И у вас может быть много способов обрабатывать их в пакетном режиме или реагируя на сохраненные события.
Высокое использование памяти: я думаю, что это должно быть так же, как только вы построили свою проекцию
Более длительное время загрузки: если сторона чтения кэширует свои проекции и "запоминает" последнее событие обновления, она не должна повторно применять всю последовательность событий. Снимки - это смягчение, но если вы делаете много снимков, возможно, вы сделали неправильный выбор с ES. Я думаю, что эта проблема является незначительной в экосистемах микросервисов, где время загрузки может быть замаскировано без прерывания обслуживания. Фактически, вы получаете максимальную отдачу от ES/CQRS, когда применяете ее, так что микросервисы
Окончательная согласованность: в этом виновата теорема CAP, а не ES. Многие не ES/CQRS должны иметь дело с этим, но есть много сценариев, где это не является реальной проблемой. Это scnearios, где ES хорошо вписывается. И вы можете смешивать ES и не ES-сервисы на одной платформе
Сериализованные события в хранилище событий: если важно иметь несериализованное представление событий, вы можете использовать БД, ориентированную на документы, но если вы делаете это для запросов к полезной нагрузке событий, вам не хватает точки ES/CQRS. ES означает перенос всех манипуляций с данными со стороны БД на уровень приложений, где каждый элемент быстро меняется, и все не зависит от статистики. Это повышает масштабируемость и отказоустойчивость и предоставляет средства для формирования организации вашей команды, делая такие вещи, как позволить внешнему парню/девушке легко написать свой BFF в javascript.
Я надеюсь применить на практике эти принципы с хорошим результатом и использовать преимущества этого захватывающего подхода