Eventual consistency

Обсуждаем, как правильно строить приложения
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Eventual consistency

Сообщение sda »

В книгах по ddd пишут, что желательно сохранять только 1 агрегат в транзакции. Если агрегат требует, чтобы родственные ему агрегаты тоже как-то изменили своё состояние, то предлагают использовать eventual consistency при помощи domain events.

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

Как вы это решаете? Знаете что почитать на эту тему? Особенно интересны решения в контексте nosql баз данных где транзакций нет вообще.
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

sda писал(а): Особенно интересны решения в контексте nosql баз данных где транзакций нет вообще.
DDD не может решить проблему отсутствия транзакций в выбранной БД.
Транзакции в некоторых NoSQL-решениях можно эмулировать с помощью операции compare-and-set: https://habrahabr.ru/post/153321/
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

Но мне не нужны транзакции. Мне нужно реализовать надежный eventual consistency.
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

Что вы понимаете под "eventual consistency"? Не уверен, что правильно понимаете и применяете этот термин. Он не про DDD, а про распределённое хранение данных. Можете цитату из книги дать на английском?
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

Насколько я понимаю, в контексте DDD "Eventual Consistency" означает, что вся цепочка событий будет рано или поздно гарантированно выполнена, даже если между событиями может пройти какое-то значительное время. Раньше сталкивался с этим термином только в пределах репликации данных между MySQL-серверами.

Собственно, в этой же статье и ответ есть на ваш вопрос:
When the Model Store and the Messaging System don’t share the same Transaction Scope, the events should be initially saved in the model store and then forwarded to the messaging system. This ensures Domain Events are not lost when there is a fault.
То есть сохранение событий и данных нужно завернуть в одну транзакцию, а потом "реплицировать" событие из хранилища данных в хранилище очереди событий, после этого уже выполнить событие.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Eventual consistency

Сообщение zelenin »

создаем сущность A, событие о ее создании кидаем в шину, подписчик на событие запрашивает новые события, шина отдает ему событие, подписчик получает событие и создает на его основе сущность Б.
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

zelenin писал(а):создаем сущность A, событие о ее создании кидаем в шину...
Между этими двумя действиями:
1) создаём сущность А
2) событие кидаем в шину

- как раз и может произойти сбой, о котором спрашивает ТС.
"Eventual Consistency" в случае такого сбоя не будет достигнута.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Eventual consistency

Сообщение zelenin »

rugabarbo писал(а):
zelenin писал(а):создаем сущность A, событие о ее создании кидаем в шину...
Между этими двумя действиями:
1) создаём сущность А
2) событие кидаем в шину

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

Microservices: From Design to Deployment https://www.nginx.com/resources/library ... oservices/
Chapter 5. Event-Driven Data Management for Microservices
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

rugabarbo, прочитал предложенную вами статью. Под sql примерно понятно как делать, под nosql нет. Также я из примеров не понял, кто и как вызывает EventForwarderService::ForwardEvents() ? Если это простой поллинг базы раз в N времени, то это печальное решение. Есть еще замечания к такой реализации, но они менее важные. Понять бы как сделать это под nosql и при этом сохранить распределенность базы.

zelenin, что-то не приходит линк на книгу, вместо неё спам :(
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Eventual consistency

Сообщение zelenin »

там не ссылка, а аттач в письме
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

sda писал(а):Под sql примерно понятно как делать, под nosql нет. Также я из примеров не понял, кто и как вызывает EventForwarderService::ForwardEvents() ? Если это простой поллинг базы раз в N времени, то это печальное решение. Есть еще замечания к такой реализации, но они менее важные. Понять бы как сделать это под nosql и при этом сохранить распределенность базы.
1. Что именно неясно в NoSQL?
2. Даже если это и polling, то он тоже позволяет добиться "Eventual Consistency". Чем не подходит? Что там печального? Мы же говорим о согласованности в конечном счёте, когда важно не мгновенное выполнение событий друг за другом, а гарантированность их выполнения вообще (хоть когда-нибудь, даже в отложенном виде).
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

1. Что именно неясно в NoSQL?
В монго атомарность гарантируется на уровне документа. Мы не можем атомарно добавить документы в несколько коллекций (таблиц в контексте sql). Даже в одну коллекцию не можем атомарно добавить 2 и более документа.
2. Даже если это и polling, то он тоже позволяет добиться "Eventual Consistency". Чем не подходит? Что там печального?
Да позволяет. Но это примитивное решение. Бесконечно бомбить запросами 99% из которых будут бесполезными. Кроме того, мне нужно максимально сократить время до того момента, когда данные станут консистентны. Если это можно сделать за 5 миллисекунд. Я хочу делать это за 5 миллисекунд. Я не хочу, чтобы пользователь выполнил действие, а потом все сидели и ждали 1 минуту пока обновится их UI в распределенном реалтайм приложении. Это просто неприемлемо. Другое дело, если событие сразу ставится в очередь, обрабатывается с минимальными сетевыми задежками и в конце, когда все агрегаты изменили свои состояния по вебсокету отправляются необходимые данные, чтобы UI отобразил эти изменения. В таком случае, даже попасть внутрь лага, когда данные неконсистентны пользователю будет практически невозможно. Но даже если это будет случаться, это не страшно. Он не успеет моргнуть глазом, как они придут в консистентное состояние.
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

1. Я дал выше статью про атомарную операцию CAS, с помощью которой эмулируются транзакции в монго: https://habrahabr.ru/post/153321/ - чем не устраивает?

2. sda, вы не могли бы разложить конкретную последовательность событий, которую вы выполняете? Например, "пользователь нажимает купить" > "менеджер получает уведомление о заказе" > "пользователю на почту поступает уведомление о том, что заказ принят". А то мы говорим про абстрактную цепочку событий, и вы начинаете к ней предъявлять помимо требования надёжности ещё и требование скорости, но, например, при той же отправке писем заявленные вами 5 мс не всегда возможны. Во-вторых, поллинг - это лишь один из способов реализации. Можно использовать и любой другой подход для надёжной идемпотентной обработки событий на бэкенде (например, демон).

3. Ещё вы должны понимать, что абсолютной надёжности не бывает. Бывает её приемлемый уровень, с учётом которого архитектор закладывает в систему тот или иной инструментарий. Любая консистентность условна. Неясно, например, почему при высоких требованиях к консистентности вы пытаетесь использовать NoSQL? Ведь NoSQL - это вообще не про консистентность. Это как раз-таки про скорость и распределённость в ущерб надёжности и консистентности.
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

Про этот алгоритм транзакций я читал. Это скорее хак, чем решение. Ревью этого решения из компетентных людей никто не делал. Много писали про nosql и eventual consistency, но при этом я не могу найти ни одного примера под nosql. Вот это удивляет. CAS поддерживают не все nosql, следовательно это не универсальное решение для реализации nosql + eventual consistency. Должны существовать другие, раз об этом вообще пишут.

Делаем пошаговую игру. Последовательность событий, упрощенно: пользователь выставляет ход > начисляем опыт за успешный ход > отнимаем жизни у оппонента > пишем в лог игры. В итоге действие "пользователь выставляет ход" требует, чтобы были изменены 3 разных агрегата. Если вы знаете, другие подходы кроме поллинга, дайте примеры где посмотреть.

Используем nosql так как в первую очередь важна распределенность. Мы готовы к потере данных. Мы не готовы к тому, что целостность данных никогда не придет в консистентное состояние. Я с вами не согласен, что любая консистентность условна. И вопрос не об этом. Нам мало интересно, какие проблемы с консистентностью могут быть на стороне базы данных. Нас интересует, как нам сделать так, чтобы eventual consistency не ломался (чтобы обновлялся агрегат и событие об этом гарантированно уходило в очередь).
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Eventual consistency

Сообщение zelenin »

не улавливаю: чего обсуждаем-то? причем тут nosql или консистентность событий?
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

Используется nosql. Транзакций нет. Нужно изменить состояние у 3 агрегатов. Есть решение?
Аватара пользователя
rugabarbo
Сообщения: 1063
Зарегистрирован: 2015.06.21, 16:21
Контактная информация:

Re: Eventual consistency

Сообщение rugabarbo »

sda, ваша проблема в том, что не порезали слона на части. У вас очень много требований и вы их все засунули под один заголовок "Eventual Consistency".

1. Разрежьте слона по частям. Давайте разбирать по отдельности каждую проблему.
2. Если говорить конкретно про "Eventual Consistency" (по теме), то по нему у вас лишь один вопрос: "Как нам сделать так, чтобы eventual consistency не ломался (чтобы обновлялся агрегат и событие об этом гарантированно уходило в очередь)?" - и вам на него уже много раз ответили в разной форме и я, и Зеленин. Вот один из ответов:
When the Model Store and the Messaging System don’t share the same Transaction Scope, the events should be initially saved in the model store and then forwarded to the messaging system. This ensures Domain Events are not lost when there is a fault.
Всё остальное - это уже бивни, хобот, уши... Это другие проблемы, которые с "Eventual Consistency" не связаны. Например, вы говорите, что вас не устраивает "хак" с эмуляцией транзакций в NoSQL. Но очевидно ведь, что это не проблема "Eventual Consistency", это проблема выбора хранилища для очереди событий.

Режьте слона.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Eventual consistency

Сообщение zelenin »

sda писал(а):Используется nosql. Транзакций нет. Нужно изменить состояние у 3 агрегатов. Есть решение?
если транзакций нет, то ничего их не добавит (и вообще к Eventual consistency это не относится). надо разрабатывать архитектуру, независящую от транзакций, т.е. использующую шину сообщений.
Для конкретного кейса - игра - идеально подойдет event sourcing. Я бы даже настоял, что оно должно быть применено, т.к. при существующем событии (СделанХод, НанесенУдар, КинутаКость) неконсистентность состояния просто невозможна, т.к. состояние и есть поток событий.
sda
Сообщения: 334
Зарегистрирован: 2013.12.19, 09:29

Re: Eventual consistency

Сообщение sda »

zelenin, я не понимаю. НанесенУдар - затрагивает 2 разных агрегата (на самом деле еще больше). Одному агрегату нужно добавить опыта, другому агрегату нужно вычесть жизни. DDD говорит о том, что не следует сохранять более одного агрегата за раз и что для таких кейсов следует пользоваться EC. Я не понимаю чем может помочь event sourcing. Будет точно такая же проблема "Читаем хранилище событий > обрабатываем событие в котором сохраняем агрегат, генерируем и сохраняем еще 1 событие". Приходим к той же самой проблеме, как атомарно сохранить агрегат + событие в nosql.

rugabarbo, хорошо, какое бы вы посоветовали хранилище? И что там на счет других решений кроме поллинга?
Ответить