2012-04-17 4 views
4

Мы начинаем новый проект, где мы хотим внедрить архитектуру CQRS + Event Sourcing с помощью MongoDB. У нас уже есть некоторый опыт работы с подходом CQRS: в нашем предыдущем проекте мы использовали исходную точку Fohjin (ну, мы реорганизовали ее значительно). В этом случае мы использовали Oracle как хранилище, а также реализовали 2PC с TransactionScope.CQRS, база данных событий и база данных NoSQL

Но для нашего нового проекта мы хотим использовать MongoDB из-за его масштабируемости и производительности. Мы определенно хотим использовать его для чтения (отчета) и использовать его для хранилища событий. Альтернативой здесь является использование SQL Server для хранения событий. Поэтому нам нужно сделать выбор. Что мне не нравится в гибридном решении, это TransactionScope, что дорого и медленно, и необходимость поддерживать разные типы Db (Mongo и SQL).

Мы смотрели на NCQRS, но нам кажется, что мы не хотим сильно зависеть от любой структуры, которая диктует много вещей, которые могут быть реализованы по-разному с нашей точки зрения. Итак, теперь мы думаем о чем-то более легком, таком как магазин событий Джонатана Оливера. Мне нравится концепция потоков и коммиттов, а также поддерживает MongoDB. Что я до сих пор не понимаю, как он обрабатывает все эти 2PC-вещи (указано, что для NoSQL). В нашем случае нам нужно ускорить события для нескольких обработчиков событий: какой-то деномализатор, который обновляет базу данных чтения и планировщик заданий для определенных типов событий. Если что-то пойдет не так с этими обработчиками, и мы получили освобождение, нет возможности отменить фиксацию для MongoDB. Есть ли трюк, чтобы справиться с этим?

Я ценю любые комментарии о том, как принять правильное решение и какие плюсы и минусы.

ответ

4

В EventStore используется Guid, чтобы однозначно идентифицировать фиксацию в базе данных, чтобы предотвратить сохранение одного и того же потока событий более одного раза. Обычно этот Guid встроен непосредственно в сообщение, уникально идентифицируя это конкретное сообщение и может использоваться как CommitId при вызове CommitChanges в потоке событий. Аналогичный подход можно использовать при обработке событий на стороне запроса в вашей системе.

Некоторые подробнее о 2PC и избегая распределенных транзакций:

+0

Спасибо за ваш ответ, Эллиот. Насколько я понимаю, мне нужно сделать мои обработчики событий/конвейерными крючками идемпотентными, добавив какой-то фильтр, который определит, что событие/commit уже отправлено. Это звучит как добавление большого количества дополнительного кода для каждого обработчика (ну, может быть, он может быть реализован как аспект или что-то вроде этого). Busides, он добавляет новый db-запрос для каждого обработчика для проверки. Но, хорошо, мы можем назвать это «стоимостью решения». Другой вопрос - когда обрабатывать частично обработанные события/коммиты? – Voice

+0

Да, вам нужно создать инфраструктуру, чтобы сделать ваши собственные обработчики событий идемпотентными. Один из способов сделать это - включить уникальный идентификатор в свои события и включить этот идентификатор в вашу модель чтения - вы сможете узнать, обрабатывали ли вы событие более одного раза. –