Поговорим о CQRS
От: Aviator  
Дата: 04.05.11 04:20
Оценка:
Есть ряд товарищей (Greg Young, Udi Dahan, ...), которые активно пиарят данный подход к проектированию распределённой системы. С высоты птичъего полёта всё довольно прозрачно. Для чтения используем отдельный readonly хранилище, на основании прочитанных данных формируем команды на изменение состояния, отправляем команду. На сервере выполнения бизнес логики команда выполнятся, изменяя доменную модель, приводя тем самым асинхронно к изменению readonly хранилища. Если кто использовал такую архитектуру (веб или смарт клиент), очень интересно узнать мнение. Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь. Если вводить понятие операции и ждать её завершения, то получаем обычную синхронную архитектуру с кучей головной боли по корреляции между действием и реакцией на действие, т.е. смысла в этом особо нет, кроме отдельных случаев, когда требуется некоторая транзакционность. Другой вариант — синхронно кэшировать результаты операций до выполнения бизнес логики и тем самым моментально отображать их либо в readonly хранилище, либо в специализированном кэше. В этом случае получаем дополнительные предположения о результатах этих операций и формируем кэш в обход изменения доменной модели, что в общем не очень здорово. Что скажет общественность?
Re: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.05.11 05:22
Оценка:
Здравствуйте, Aviator, Вы писали:

A>Есть ряд товарищей (Greg Young, Udi Dahan, ...), которые активно пиарят данный подход к проектированию распределённой системы. С высоты птичъего полёта всё довольно прозрачно. Для чтения используем отдельный readonly хранилище, на основании прочитанных данных формируем команды на изменение состояния, отправляем команду. На сервере выполнения бизнес логики команда выполнятся, изменяя доменную модель, приводя тем самым асинхронно к изменению readonly хранилища. Если кто использовал такую архитектуру (веб или смарт клиент), очень интересно узнать мнение. Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь. Если вводить понятие операции и ждать её завершения, то получаем обычную синхронную архитектуру с кучей головной боли по корреляции между действием и реакцией на действие, т.е. смысла в этом особо нет, кроме отдельных случаев, когда требуется некоторая транзакционность. Другой вариант — синхронно кэшировать результаты операций до выполнения бизнес логики и тем самым моментально отображать их либо в readonly хранилище, либо в специализированном кэше. В этом случае получаем дополнительные предположения о результатах этих операций и формируем кэш в обход изменения доменной модели, что в общем не очень здорово. Что скажет общественность?


Подход оправдан когда обработка вводимых данных очень длительна. Тогда данные складываются в очередь, а воркеры разгребают очередь и занимаются обработкой. В остальных случаях слишком много приседаний получается для каких-то простых действий.
Re[2]: Поговорим о CQRS
От: Aviator  
Дата: 04.05.11 06:12
Оценка:
Здравствуйте, gandjustas, Вы писали:
G>Подход оправдан когда обработка вводимых данных очень длительна. Тогда данные складываются в очередь, а воркеры разгребают очередь и занимаются обработкой. В остальных случаях слишком много приседаний получается для каких-то простых действий.

Ну почему, если количество чтений значительно превышает количество изменений, то отдельные хранилища для читателей очень даже оправданы.
Re[3]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 04.05.11 06:25
Оценка: +1
Здравствуйте, Aviator, Вы писали:

A>Здравствуйте, gandjustas, Вы писали:

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

A>Ну почему, если количество чтений значительно превышает количество изменений, то отдельные хранилища для читателей очень даже оправданы.


Каким образом оправданы? Можно просто написать запрос к транзакционным таблицам в базе, а можно сделать кучу приседаний с очередями, событиями, триггерами, двумя хранилищами чтобы показать тот же результат. Как раз CQRS совсем неоправданно.
Re: Поговорим о CQRS
От: vansha Украина korneliuk.blogspot.com
Дата: 05.05.11 11:32
Оценка: 1 (1)
Здравствуйте, Aviator

Вдруг Вы не в курсе, в google groups есть интересная группа для обсуждения CQRS — https://groups.google.com/forum/#!forum/dddcqrs

В частности похожий вопрос там поднимался в этой ветке — https://groups.google.com/d/topic/dddcqrs/gvba5NDKalk/discussion
Re[2]: Поговорим о CQRS
От: Aviator  
Дата: 06.05.11 07:07
Оценка:
Здравствуйте, vansha, Вы писали:

V>Здравствуйте, Aviator


V>Вдруг Вы не в курсе, в google groups есть интересная группа для обсуждения CQRS — https://groups.google.com/forum/#!forum/dddcqrs


V>В частности похожий вопрос там поднимался в этой ветке — https://groups.google.com/d/topic/dddcqrs/gvba5NDKalk/discussion

Спасибо за ссылку, интересное обсуждение
Re: Поговорим о CQRS
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 06.05.11 10:55
Оценка:
Здравствуйте, Aviator, Вы писали:

A>...Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь.


Я сталкивался с таким работающим вариантом в похожей архитектуре:
(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
объект был создан с заданным идентификатором. С ответом клиент также
получает минимально достаточное для отображения состояние нового
объекта — название, заголовок, артикул и т.п.
(2) В клиентском кэше модели создается слот для нового объекта.
Объект отмечен как несинхронизированный.
(3) Новый слот ожидает получения полного состояния асинхронно.
(4) При получении полного состояния объект объявляется синхронизированным.

Соответственно, при такой схеме можно разрешить отображение объекта
во view сразу после получения ответа (1), но редактирование
полей и другие операции остаются недоступными до получения полного
состояния (4).
El pueblo unido jamás será vencido.
Re[2]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.05.11 11:12
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>Здравствуйте, Aviator, Вы писали:


A>>...Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь.


BB>Я сталкивался с таким работающим вариантом в похожей архитектуре:

BB>(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
BB>объект был создан с заданным идентификатором. С ответом клиент также
BB>получает минимально достаточное для отображения состояние нового
BB>объекта — название, заголовок, артикул и т.п.
BB>(2) В клиентском кэше модели создается слот для нового объекта.
BB>Объект отмечен как несинхронизированный.
BB>(3) Новый слот ожидает получения полного состояния асинхронно.
BB>(4) При получении полного состояния объект объявляется синхронизированным.

BB>Соответственно, при такой схеме можно разрешить отображение объекта

BB>во view сразу после получения ответа (1), но редактирование
BB>полей и другие операции остаются недоступными до получения полного
BB>состояния (4).

То что так можно сделать никто не сомневается, вот зачем так делать?
Re[3]: Поговорим о CQRS
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 06.05.11 11:56
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, bl-blx, Вы писали:


BB>>Здравствуйте, Aviator, Вы писали:


A>>>...Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь.


BB>>Я сталкивался с таким работающим вариантом в похожей архитектуре:

BB>>(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
BB>>объект был создан с заданным идентификатором. С ответом клиент также
BB>>получает минимально достаточное для отображения состояние нового
BB>>объекта — название, заголовок, артикул и т.п.
BB>>(2) В клиентском кэше модели создается слот для нового объекта.
BB>>Объект отмечен как несинхронизированный.
BB>>(3) Новый слот ожидает получения полного состояния асинхронно.
BB>>(4) При получении полного состояния объект объявляется синхронизированным.

BB>>Соответственно, при такой схеме можно разрешить отображение объекта

BB>>во view сразу после получения ответа (1), но редактирование
BB>>полей и другие операции остаются недоступными до получения полного
BB>>состояния (4).

G>То что так можно сделать никто не сомневается, вот зачем так делать?


Например, объект достаточно тяжеловесный и целиком его загружать на
клиента необходимости нет. Тем не менее пользователю нужен визуальный
фидбек о том, что объект нормально создался.
El pueblo unido jamás será vencido.
Re[4]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.05.11 13:37
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>>>Я сталкивался с таким работающим вариантом в похожей архитектуре:

BB>>>(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
BB>>>объект был создан с заданным идентификатором. С ответом клиент также
BB>>>получает минимально достаточное для отображения состояние нового
BB>>>объекта — название, заголовок, артикул и т.п.
BB>>>(2) В клиентском кэше модели создается слот для нового объекта.
BB>>>Объект отмечен как несинхронизированный.
BB>>>(3) Новый слот ожидает получения полного состояния асинхронно.
BB>>>(4) При получении полного состояния объект объявляется синхронизированным.

BB>>>Соответственно, при такой схеме можно разрешить отображение объекта

BB>>>во view сразу после получения ответа (1), но редактирование
BB>>>полей и другие операции остаются недоступными до получения полного
BB>>>состояния (4).

G>>То что так можно сделать никто не сомневается, вот зачем так делать?


BB>Например, объект достаточно тяжеловесный и целиком его загружать на

BB>клиента необходимости нет. Тем не менее пользователю нужен визуальный
BB>фидбек о том, что объект нормально создался.

А чем такое решение лучше, чем запись в транзакционную таблицу и чтение потом из нее?
Re[5]: Поговорим о CQRS
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 06.05.11 14:01
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, bl-blx, Вы писали:


BB>>>>Я сталкивался с таким работающим вариантом в похожей архитектуре:

BB>>>>(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
BB>>>>объект был создан с заданным идентификатором. С ответом клиент также
BB>>>>получает минимально достаточное для отображения состояние нового
BB>>>>объекта — название, заголовок, артикул и т.п.
BB>>>>(2) В клиентском кэше модели создается слот для нового объекта.
BB>>>>Объект отмечен как несинхронизированный.
BB>>>>(3) Новый слот ожидает получения полного состояния асинхронно.
BB>>>>(4) При получении полного состояния объект объявляется синхронизированным.

BB>>>>Соответственно, при такой схеме можно разрешить отображение объекта

BB>>>>во view сразу после получения ответа (1), но редактирование
BB>>>>полей и другие операции остаются недоступными до получения полного
BB>>>>состояния (4).

G>>>То что так можно сделать никто не сомневается, вот зачем так делать?


BB>>Например, объект достаточно тяжеловесный и целиком его загружать на

BB>>клиента необходимости нет. Тем не менее пользователю нужен визуальный
BB>>фидбек о том, что объект нормально создался.

G>А чем такое решение лучше, чем запись в транзакционную таблицу и чтение потом из нее?


В простом случае, видимо, ничем. Но, к примеру, когда часть состояния объекта
создаётся асинхронно другой системой (одной или несколькими), то момент
когда можно успешно считать полное состояние не известен. В результате часто
эффективным решением на клиентской стороне оказывается асинхронный запрос снимка
состояния с одновременной подпиской на обновления.
El pueblo unido jamás será vencido.
Re[6]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.05.11 15:13
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>>>Например, объект достаточно тяжеловесный и целиком его загружать на

BB>>>клиента необходимости нет. Тем не менее пользователю нужен визуальный
BB>>>фидбек о том, что объект нормально создался.

G>>А чем такое решение лучше, чем запись в транзакционную таблицу и чтение потом из нее?


BB>В простом случае, видимо, ничем. Но, к примеру, когда часть состояния объекта

BB>создаётся асинхронно другой системой (одной или несколькими), то момент
BB>когда можно успешно считать полное состояние не известен. В результате часто
BB>эффективным решением на клиентской стороне оказывается асинхронный запрос снимка
BB>состояния с одновременной подпиской на обновления.

Ну то есть мы в обычную "транзакционную таблицу" кладем запись с состоянием "обрабатывается", отправляем воркеру сообщение что надо провести какую-нибудь длительную операцию, он эту операцию проводит и обновляет запись. Такое как-бы повсеместно используется для этих самых длительных операций. Причем такое применялось задолго до того как придумали аббревиатуру CQRS. Зачем в других случаях нужен такой подход — непонятно.

Собственно не вижу смысла в создании подобной инфраструктуры в остальных случаях.
Re[3]: Поговорим о CQRS
От: Sorc17 Россия  
Дата: 06.05.11 17:21
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, bl-blx, Вы писали:


BB>>Здравствуйте, Aviator, Вы писали:


A>>>...Меня очень смущает тот досадный факт, что обычно данные, которые изменяет пользователь нужно оперативно сделать видимыми для этого пользователя. Например после нажатии кнопочки "submit" на добавление записи в блог типичный юзер очень расстроится, если увидит свою запись только после десятого рефреша. Возникает вопрос как этого достичь.


BB>>Я сталкивался с таким работающим вариантом в похожей архитектуре:

BB>>(1) По сабмиту получаем синхроный ответ от бизнес-логики о том, что
BB>>объект был создан с заданным идентификатором. С ответом клиент также
BB>>получает минимально достаточное для отображения состояние нового
BB>>объекта — название, заголовок, артикул и т.п.
BB>>(2) В клиентском кэше модели создается слот для нового объекта.
BB>>Объект отмечен как несинхронизированный.
BB>>(3) Новый слот ожидает получения полного состояния асинхронно.
BB>>(4) При получении полного состояния объект объявляется синхронизированным.

BB>>Соответственно, при такой схеме можно разрешить отображение объекта

BB>>во view сразу после получения ответа (1), но редактирование
BB>>полей и другие операции остаются недоступными до получения полного
BB>>состояния (4).

G>То что так можно сделать никто не сомневается, вот зачем так делать?


Вы оставляете сообщение на rsdn и оно мгновенно появляется в треде в вашем браузере с помощью яваскриптоты, но без некоего порядкового номера. А все остальные его увидят только через какое-то время уже с порядковым номером. И в то же при обновлении страницы у вас в браузере ваше сообщение тоже обретёт порядковый номер и его можно будет отредактировать или ещё что-то сделать с ним
Для нас [Thompson, Rob Pike, Robert Griesemer] это было просто исследование. Мы собрались вместе и решили, что ненавидим C++ [смех].
Re[4]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.05.11 07:13
Оценка:
Здравствуйте, Sorc17, Вы писали:

G>>То что так можно сделать никто не сомневается, вот зачем так делать?


S>Вы оставляете сообщение на rsdn и оно мгновенно появляется в треде в вашем браузере с помощью яваскриптоты, но без некоего порядкового номера. А все остальные его увидят только через какое-то время уже с порядковым номером. И в то же при обновлении страницы у вас в браузере ваше сообщение тоже обретёт порядковый номер и его можно будет отредактировать или ещё что-то сделать с ним


А причем тут CQRS? Это чисто клиентские вещи, можно так при любой архитектуре на сервере сделать.
Re: Поговорим о CQRS
От: DmytroL Украина http://www.linkedin.com/in/dmytrol
Дата: 14.06.11 16:35
Оценка:
Здравствуйте, Aviator, Вы писали:

A>Есть ряд товарищей (Greg Young, Udi Dahan, ...), которые активно пиарят данный подход к проектированию распределённой системы. С высоты птичъего полёта всё довольно прозрачно. Для чтения используем отдельный readonly хранилище, на основании прочитанных данных формируем команды на изменение состояния, отправляем команду. На сервере выполнения бизнес логики команда выполнятся, изменяя доменную модель, приводя тем самым асинхронно к изменению readonly хранилища.


Возможно, я невнимательно читал или не так понял, но у меня сложилось впечатление, что суть CQRS не в асинхронности, а в том, чтобы обходить доменную модель и ORM (а вместе с ней — и дорогую материализацию в POCO/POJO/и т.п.) в тех случаях, когда данные надо получать только для чтения, как правило, в виде проекции от нескольких связанных сущностей с ограниченными подмножествами атрибутов каждой из сущностей. То есть, то, с чем любая приличная реляционная СУБД справится намного лучше и быстрее.

И, ИМХО, CQRS — это всего лишь "противоядие" (а на самом деле, здравый смысл) от уж слишком ортодоксального воплощения шаблона "модель предметной области", когда любой "чих" по чтению данных делается исключительно через ORM и материализацию.

P.S. Решения, в которых используются NoSQL хранилища данных — отдельная песня, там, возможно, CQRS смысла не имеет по причине того, что все реляционные операции все равно надо делать уровнем выше, и почему бы этим уровнем не быть как раз ORM?
Re[4]: Поговорим о CQRS
От: -VaS- Россия vaskir.blogspot.com
Дата: 14.06.11 17:53
Оценка:
G>Каким образом оправданы? Можно просто написать запрос к транзакционным таблицам в базе, а можно сделать кучу приседаний с очередями, событиями, триггерами, двумя хранилищами чтобы показать тот же результат. Как раз CQRS совсем неоправданно.

Запрос то написать можно. А что если он отрабатывает 2 минуты? А если 18 часов? Ну например, пользователь хочет пофильтровать по 3 полям и посортировать еще по двум таблицу в 800 млн. записей. Заджойненную на другие 3 таблицы, каждая по 10 млн?

Суть CQRS — в денормализованном, оптимизированном на запросы read-only хранилище.
Re[5]: Поговорим о CQRS
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.06.11 23:54
Оценка:
Здравствуйте, -VaS-, Вы писали:

G>>Каким образом оправданы? Можно просто написать запрос к транзакционным таблицам в базе, а можно сделать кучу приседаний с очередями, событиями, триггерами, двумя хранилищами чтобы показать тот же результат. Как раз CQRS совсем неоправданно.


VS>Запрос то написать можно. А что если он отрабатывает 2 минуты? А если 18 часов? Ну например, пользователь хочет пофильтровать по 3 полям и посортировать еще по двум таблицу в 800 млн. записей. Заджойненную на другие 3 таблицы, каждая по 10 млн?


Indexed\materialized view

VS>Суть CQRS — в денормализованном, оптимизированном на запросы read-only хранилище.


А как при тех же объемах поможет CQRS?
Re: Поговорим о CQRS
От: Miroff Россия  
Дата: 16.06.11 11:13
Оценка: +1
Здравствуйте, Aviator, Вы писали:

A>Что скажет общественность?


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

Если очень хочется, вариант с инвалидацией кэшей единственный выглядит рабочим. Когда операция встает в очередь, сразу же апдейтятся кэши. Поскольку на чтение данные берутся из кэшей, пользователь увидит изменения до того как они реально лягут в базу. Да, какую-то часть бизнес-логики придется выполнять до того как операция встанет в очередь. Но это небольшая проблема, поскольку львиная доля всех операций это банальный crud. Для сложных операций можно добавлять плейсхолдеры в стиле "тут будет ваше сообщение, когда мы соблаговолим его запроцессить". Возможны некоторые шероховатости, например, в кэшах лежит только brief а пользователь захотел смотреть полную сущность, но при грамотном построении интерфейса они сгладятся сами.

Важный момент: существование очереди не означает что операции будут висеть в ней долго. В норме очередь пустая и каждая операция выполняется тотчас как он попала в очередь (с поправкой на латентность сети). Сама очередь нужна для того чтобы:
1. Повысить отзывчивость интерфейса. Теперь пользователь не ждет пока его операция запроцессится, а отправляется заниматься своими делами.
2. Обеспечить устойчивость системы при пиковых нагрузках. В новый год все отправляют друг другу поздравления. Эти поздравления никуда не теряются хотя и могут добраться до адресата только через несколько часов. При этом пользовательский интерфейс работает без задержек и сбоев.
3. Обеспечить мониторинг работы системы. С очередей легко снимать статистику по типам операций, времени выполнения, профилю нагрузки и т.п.
4. Повысить горизонтальную масштабируемость системы. Если мы видим, что очереди начали расти, мы просто добавляем еще один воркер.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.