CQRS, Event Sourcing и Scaling - PullRequest
       12

CQRS, Event Sourcing и Scaling

0 голосов
/ 06 июня 2018

Понятно, что система, основанная на этих шаблонах, легко масштабируется.Но я хотел бы спросить вас, как именно?У меня есть несколько вопросов относительно масштабируемости:

  1. Как масштабировать агрегаты?Если я создам несколько экземпляров aggregate A, как их синхронизировать?Если один из экземпляров обрабатывает команду и создает событие, это событие должно распространяться на каждый экземпляр этого агрегата?
  2. Разве не должна присутствовать какая-то бизнес-логика, какой экземпляр агрегата запрашивать?Поэтому, если я выполняю несколько команд, которые применяются к aggregate A (ORDERS) и применяются к одному конкретному заказу, имеет смысл доставить его в один и тот же экземпляр.Или?

В этой статье: https://initiate.andela.com/event-sourcing-and-cqrs-a-look-at-kafka-e0c1b90d17d8, они используют Кафку с разметкой.Таким образом, служба управления пользователями - агрегат масштабируется, но подписывается только на определенный раздел темы, который содержит все события конкретного пользователя.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Как масштабировать агрегаты?

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

To borrow from your example, an example of smaller responsibilities would
be to shift from one aggregate for all ORDERS to one aggregate for _each_
ORDER.

It's analogous to the difference between having a key value store with
all ORDERS stored in a document under one key, vs each ORDER being stored
using its own key.

Чтения безопасны, вы можете масштабировать их с несколькими копиями.Однако эти копии только в конечном итоге согласуются.Это означает, что если вы спросите "какова цена предложения FCOJ сейчас ?"Вы можете получить разные ответы от каждой копии.В качестве альтернативы, если вы спросите "какова была цена предложения FCOJ в 10:09:02?"тогда каждая копия либо даст вам один ответ, либо скажет «я еще не знаю».

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

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

Acquire a message
Compute the storage key
Load a versioned representation from storage
Compute a new versioned representation
Store.compare and swap the new representation for the old

Чтобы обеспечить дополнительную пропускную способность трафика, вы добавляете больше вычислений без сохранения состояния.

Чтобы обеспечить пропускную способность хранилища,Вы распределяете ключи по нескольким устройствам хранения.

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

Протоколы здравых сообщений важны;см. Марка де Грауу. Никому не нужен надежный обмен сообщениями .

0 голосов
/ 07 июня 2018

Как масштабировать агрегаты?

Экземпляры агрегатов представлены их потоком событий.Каждый экземпляр Aggregate имеет свой собственный поток событий.События из одного агрегатного экземпляра НЕ используются другими агрегатными экземплярами.Например, если Order Aggregate с ID = 1 создает событие OrderWasCreated с ID = 1001, это событие НИКОГДА не будет использоваться для повторной гидратации других экземпляров Order Aggregate (с ID = 2,3,4 ...).

При этом вы масштабируете агрегаты по горизонтали, создавая сегменты в хранилище событий на основе идентификатора агрегата.

Если я создам несколько экземпляров агрегата A, как синхронизироватьих?Если один из экземпляров обрабатывает команду и создает событие, это событие должно распространяться на каждый экземпляр этого агрегата?

Вы этого не делаете.Каждый экземпляр Aggregate полностью отделен от других экземпляров.

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

Не должно ли присутствовать бизнес-логики, какой экземпляр агрегата запрашивать?Поэтому, если я выполняю несколько команд, которые применяются к агрегату A (ORDERS) и применяются к одному конкретному заказу, имеет смысл доставить его в один и тот же экземпляр.Или?

Вы предполагаете, что экземпляры Aggregate постоянно работают в ОЗУ некоторых серверов.Вы могли бы сделать это, но такая архитектура очень сложна.Например, что происходит, когда один из серверов выходит из строя и его необходимо заменить другим?Трудно определить, в каких случаях там жить, и перезапустить их.Вместо этого у вас может быть много серверов без состояния , которые могут обрабатывать команды для любого из агрегатных экземпляров.Когда приходит команда, вы идентифицируете Aggregate ID, загружаете его из хранилища событий, воспроизводя все предыдущие события, и затем он может выполнить команду.После выполнения команды и сохранения новых событий в хранилище событий вы можете отказаться от экземпляра Aggregate.Следующая команда, поступающая для того же экземпляра Aggregate, может быть обработана любым другим сервером без состояния .Таким образом, масштабируемость определяется только масштабируемостью самого хранилища событий.

0 голосов
/ 06 июня 2018

Как масштабировать агрегаты?

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

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

, какой экземпляр агрегата дляrequest?

В нашей reSolve Framework мы создаем экземпляр агрегата для каждой команды и не храним его между запросами.Это работает на удивление быстро - быстрее извлечь 100 событий и привести их к агрегатному состоянию, чем найти правильный агрегатный экземпляр в кластере.

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

...