Что такое Event Sourcing (Событийное снабжение)?

Ответ

Event Sourcing — это архитектурный паттерн, при котором все изменения состояния приложения сохраняются в виде последовательности неизменяемых событий. Текущее состояние системы не хранится напрямую, а вычисляется путем последовательного применения всех событий с самого начала.

Журнал событий становится единственным источником правды (Single Source of Truth).

Основная идея:
Вместо того чтобы выполнять UPDATE User SET status = 'active' WHERE id = 123, мы сохраняем событие UserActivated { UserID: 123, Timestamp: ... }.

Пример на Go:

// События
type AccountCreated struct {
    ID      string
    Owner   string
}
type MoneyDeposited struct {
    Amount int
}
type MoneyWithdrawn struct {
    Amount int
}

// Агрегат (сущность)
type Account struct {
    ID      string
    Owner   string
    Balance int
}

// Восстановление состояния из истории событий
func NewAccountFromEvents(events []interface{}) *Account {
    a := &Account{}
    for _, event := range events {
        a.Apply(event)
    }
    return a
}

// Применение одного события к состоянию
func (a *Account) Apply(event interface{}) {
    switch e := event.(type) {
    case AccountCreated:
        a.ID = e.ID
        a.Owner = e.Owner
    case MoneyDeposited:
        a.Balance += e.Amount
    case MoneyWithdrawn:
        a.Balance -= e.Amount
    }
}

Преимущества:

  • Полный аудиторский след: Всегда можно узнать, кто, что и когда изменил, так как вся история сохранена.
  • Отладка и "путешествия во времени": Можно восстановить состояние системы на любой момент в прошлом, что упрощает отладку.
  • Аналитика: Легко строить различные проекции данных (модели для чтения) на основе одного и того же журнала событий.

Недостатки:

  • Сложность реализации: Паттерн сложнее для понимания и реализации, чем традиционное CRUD-хранение.
  • Версионирование событий: Если структура события меняется, нужно поддерживать обратную совместимость для корректного воспроизведения старых событий.
  • Производительность восстановления: Восстановление состояния для сущностей с очень длинной историей может быть медленным (решается с помощью снимков состояния — snapshots).

Связь с CQRS:
Event Sourcing часто используется вместе с паттерном CQRS (Command Query Responsibility Segregation), где модели для записи (основанные на событиях) отделены от моделей для чтения (оптимизированных для запросов).