Недавно я начал погружаться в CQRS / ES, потому что мне может понадобиться применить его на работе. Это кажется очень многообещающим в нашем случае, поскольку это решило бы много проблем.
Я набросал свое грубое понимание того, как приложение ES / CQRS должно выглядеть в контексте с упрощенным банковским сценарием (снятие денег).
Чтобы подвести итог, если человек А снимает деньги:
- команда выдана
- команда передана для проверки / подтверждения
- событие передается в хранилище событий, если проверка прошла успешно
- агрегатор удаляет событие, чтобы применить изменения к агрегату
Из того, что я понял, журнал событий является источником правды, так как это журнал ФАКТОВ, мы можем затем извлечь из него любую проекцию.
Теперь, что я не понимаю, в этой великой схеме вещей, что происходит в этом случае:
- Правило: баланс не может быть отрицательным
- человек А имеет баланс 100e
- человек A выдает команду на снятие 100e
- проходит валидация и отправляется событие MoneyWithdrewEvent 100e
- тем временем, человек А выпускает другую команду WithdrawCommand со значением 100e
- первый MoneyWithdrewEvent еще не был агрегирован, поэтому проверка проходит успешно, так как проверка проверки по совокупности (которая еще не была обновлена)
- MoneyWithdrewEvent of 100e выдается в другой раз
==> Мы находимся в несогласованном состоянии с балансом -100e, а журнал содержит 2 MoneyWithdrewEvent
Как я понимаю, есть несколько стратегий, чтобы справиться с этой проблемой:
- a) поместите агрегированный идентификатор версии вместе с событием в хранилище событий, чтобы при несоответствии версий при модификации ничего не происходило
- б) использовать некоторые стратегии блокировки, подразумевая, что уровень проверки должен каким-то образом создать
Вопросы, связанные со стратегиями:
- а) В этом случае журнал событий больше не является источником правды, как с этим бороться? Кроме того, мы вернулись к клиенту ОК, тогда как было разрешено снятие средств, лучше ли в этом случае использовать блокировки?
- б) замки == тупики, есть ли у вас какие-либо идеи о лучших практиках?
В целом, правильно ли я понимаю, как справиться с параллелизмом?
Примечание: я понимаю, что один и тот же человек, снимающий два раза деньги за такое короткое время, невозможен, но я взял простой пример, чтобы не потеряться в деталях