Событийная архитектура по своей природе асинхронна. Это значит, что система работает в режиме Eventual Consistency (Согласованность в конечном счете). Данные в разных микросервисах могут быть временно рассинхронизированы.
Если мы используем паттерн Event-Carried State Transfer (когда событие несет все данные внутри себя), консьюмер рискует обработать «устаревшую» версию объекта, которая где-то застряла в брокере. Например, отмененный заказ может снова стать «подтвержденным».
Как с этим бороться?
- Версионирование (Event Versioning): Каждое изменение сущности увеличивает счетчик
в БД. Это поле передается в событии. Консьюмер сохраняет у себя номер последней версии. Если приходит событие с версией меньше текущей — оно отбрасывается как устаревшее.Version - Откат к Event Notification: Если цена ошибки слишком высока (например, списание с баланса), мы перестаем передавать данные внутри события. Событие просто говорит: «Заказ 123 изменился». А консьюмер делает синхронный GET-запрос в мастер-систему, чтобы получить 100% свежие данные на текущую миллисекунду.
Подводка к продвинутым паттернам: Мы увидели, как много проблем таит в себе слабая связность и асинхронность (Хореография). Что делать, если бизнес требует сложной транзакции из 5 шагов с гарантиями отката? Для этого мы перейдем к паттернам Оркестрации (Mediator) и SAGA.