Проект GitHub CQRS.NET содержит несколько конкретных примеров того, как вы можете создавать EventStores в нескольких различных технологиях.На момент написания этой статьи есть реализация в SQL с использованием Linq2SQL и схемы SQL , есть одна для MongoDB , одна для DocumentDB (CosmosDB, если вы в Azure) и один, использующий EventStore (как упомянуто выше).В Azure есть еще кое-что, например Table Storage and Blob Storage, которое очень похоже на плоское хранилище файлов.
Полагаю, главное здесь то, что все они соответствуют одному принципалу / контракту.Все они хранят информацию в одном месте / контейнере / таблице, они используют метаданные для идентификации одного события из другого и «просто» сохраняют все событие таким, каким оно было - в некоторых случаях сериализованным, как и поддерживающие технологии.Таким образом, в зависимости от того, выберете ли вы базу данных документов, реляционную базу данных или даже простой файл, есть несколько разных способов достижения одного и того же намерения хранилища событий (это полезно, если вы передумаете в любой момент и обнаружите, что вам нужно перенести или поддержатьнесколько технологий хранения).
Как разработчик проекта, я могу поделиться некоторыми взглядами на некоторые из сделанных нами решений.
Во-первых, мы нашли (даже с уникальными UUID / GUID вместоцелые числа) по многим причинам последовательные идентификаторы встречаются по стратегическим причинам, поэтому просто наличие идентификатора не было достаточно уникальным для ключа, поэтому мы объединили наш столбец ключа основного идентификатора с типом данных / объекта, чтобы создать то, что должно быть истинно (всмысл вашего приложения) уникальный ключ.Я знаю, что некоторые люди говорят, что вам не нужно хранить его, но это будет зависеть от того, находитесь ли вы в «зеленом поле» или вам необходимо сосуществовать с существующими системами.
Мы остановились на одном контейнере / таблице / коллекции дляпричины ремонтопригодности, но мы поиграли с отдельной таблицей для каждой сущности / объекта.На практике мы обнаружили, что это означает, что либо приложению необходимы разрешения «СОЗДАТЬ» (что, вообще говоря, не очень хорошая идея ... как правило, всегда есть исключения / исключения), либо каждый раз, когда новый объект / объект появляется или развертывается, новыйконтейнеры для хранения / столы / коллекции должны быть сделаны.Мы обнаружили, что это было очень медленно для локальной разработки и проблематично для развертывания производства.Вы не можете, но это был наш реальный опыт.
Еще одна вещь, которую нужно помнить, это то, что запрос действия X может привести к множеству различных событий, таким образом, зная все события, сгенерированные командой / событием /что нибудь полезноеОни также могут относиться к различным типам объектов, например, нажатие кнопки «купить» в корзине может вызвать срабатывание событий учетной записи и складирования.Приложение-потребитель может хотеть знать все это, поэтому мы добавили CorrelationId.Это означало, что потребитель мог запросить все события, возникшие в результате их запроса.Вы увидите, что в схеме .
В частности, с SQL, мы обнаружили, что производительность действительно стала узким местом, если индексы и разделы не использовались должным образом.Помните, что события должны быть переданы в обратном порядке, если вы используете снимки.Мы попробовали несколько разных индексов и обнаружили, что на практике для отладки реальных приложений реального мира необходимы некоторые дополнительные индексы.Опять же, вы увидите, что в схеме .
Другие производственные метаданные были полезны во время производственных исследований, временные метки дали нам представление о порядке, в котором события сохранялись, а не возникали.Это оказало нам некоторую помощь в создании системы, которая была в значительной степени управляема событиями и которая вызвала огромное количество событий, предоставив нам информацию о производительности таких вещей, как сети и распределение систем по сети.