Event sourcing хранит каждое изменение состояния как неизменяемое событие в журнале только для добавления, вместо того чтобы сохранять только текущее состояние. Это даёт полную, проверяемую историю и позволяет гибко восстанавливать состояние.
Хранилище событий принимает только однократные операции записи. Каждое событие включает:
aggregateId – идентифицирует сущностьeventType – описывает, что произошлоpayload – данные измененияsequenceNumber – обеспечивает упорядочение и включает оптимистичное управление конкурентностьюТекущее состояние восстанавливается переигрыванием событий по порядку через корневой агрегат:
currentState = initialState + applyAll(events)
Каждое событие применяется как чистая функция, что делает переигрывание детерминированным и тестируемым.
Переигрывание тысяч событий при каждой загрузке — дорогое удовольствие. Снимки фиксируют состояние агрегата на заданном sequenceNumber, поэтому нужно переигрывать только новые события:
currentState = snapshot + applyAll(events after snapshot)
Снимки хранятся отдельно и создаются периодически или после достижения порогового количества событий.
События неизменяемы, поэтому изменения схемы требуют осторожного управления:
OrderPlaced_v2)Проекции потребляют поток событий для построения материализованных представлений, оптимизированных под конкретные запросы — например, представление дашборда или таблицу отчётов. Их можно пересоздать в любой момент, переиграв события с самого начала.
Command Query Responsibility Segregation (CQRS) естественно сочетается с event sourcing:
Это разделение обеспечивает масштабируемость, независимую оптимизацию и чёткие границы системы.
В append-only event store поле sequenceNumber обеспечивает оптимистичный контроль параллелизма, позволяя нескольким одновременным записям в один aggregate перед обнаружением конфликтов.
Новый — ещё не проверен сообществом
Вы