Паттерн Event sourcing

Event sourcing разработчики никогда не теряют кошелек, так как всегда могут восстановить историю событий за день

Контекст
ПРоблемная Маша:
Мы хотим отслеживать, как изменяются данные со временем. Но обычные CRUD-системы затирают старые значения. Нам нужно видеть всю историю изменений!
Плюс, откаты и аудит — это боль.
Что делать?
Выручающий Саша:
Тебе поможет Event Sourcing. Вместо хранения текущего состояния, ты сохраняешь все события, которые к нему привели.
ПРоблемная Маша:
Подожди, то есть вообще не хранить текущие данные?
Выручающий Саша:
Да! Храни только события вроде OrderCreated, ItemAdded, PaymentConfirmed.
А текущее состояние восстанавливается проигрыванием событий.
Можно добавить снапшот - текущее состояние, чтобы ускорить работу при восстановлении.
ПРоблемная Маша:
А как это помогает?
Выручающий Саша:
  1. Полный лог того, что произошло - аудит
  2. Просто "отмени" событие или переиграй до нужного момента чтобы откатиться
  3. Публикуешь событие - другие системы реагируют
Главное — правильно проектировать события, они твоя единственная истина.
Проблема
Как поддерживать целостность и отслеживать изменения состояний в распределенных системах
Решение
Вместо хранения текущего состояния сущности вести историю изменений состояний данной сущности.
Для этого разработать статусную модель, к примеру:

OrderCreated, OrderApproved, OrderShipped, OrederRejectes, ...

И вести историю состояний по каждому ордеру, при это история не может меняться, только добавляться.
В случае восстановления актуального состояния мы проходимся по всей истории до последнего события, либо еще делаем shipment - табличку на чтение, в которой храним последнее состояние для ускорения восстановления.
Преимущества
  • Возможность воссоздать состояние системы в любой момент времени путем воспроизведения событий, что полезно при восстановлении после сбоев или для тестирования.
  • Можно вернуться в прошлое состояние, «проиграв» события до определенного момента.
    Полезно для отладки, восстановления после багов или анализа поведения системы.
  • Реплей и проекции - Можно повторно воспроизвести события для:
    Построения новых read-моделей (CQRS)
    Миграции данных
  • Упрощает аудит, отладку и анализ. Это позволяет легко понять, как система пришла к текущему состоянию
  • События можно сразу публиковать в очереди (Kafka, RabbitMQ и т.д.). Проще интегрироваться с другими сервисами
  • События неизменяемы (append-only)
    Повышает надежность
    Позволяет эффективно кэшировать
    Делает данные удобными для репликации и масштабирования
Недостатки
  • Повышенная сложность разработки
    Состояние не хранится напрямую — нужно восстанавливать его из цепочки событий.
    Нужны агрегаты, обработчики событий, read-модели и прочая инфраструктура.
  • События нельзя менять задним числом
    Самое важное сразу разработать хорошую событийную модель.
  • Нельзя просто изменить структуру события
    Вводить версии событий
    Делать миграции
    Использовать upcaster(в рантайме преобразовывать старые версии событий)
  • Производительность восстановления
    При большом числе событий может быть медленно восстанавливать агрегат
    Поэтому часто используют:
    • Снапшоты
    • Или read-модели (CQRS)
Онлайн-школа профессионального программирования на java для коммерческих разработчиков и соискателей.
2 главные задачи, которые мы решаем:
  1. Трудоустройство и успешное прохождение испыталки.
  2. Переход на современный стек middle+
Наше главное достояние:
Менторская поддержка 24/7 и обучение в формате живого общения
Получить консультацию по обучению