Знакомимся с Event Sourcing. Часть 2

Автор оригинала: Stuart Bingë
  • Перевод
Перевод статьи подготовлен в преддверии старта курса «Java Developer. Professional».
Читать первую часть.





Особенности реализации Event Sourcing


С технической точки зрения для Event Sourcing требуется только реализация записи событий в журнал и чтения из журнала.

В простейшем случае в качестве хранилища событий может использоваться файл, в котором в каждой строке записывается отдельное событие, или несколько файлов, когда каждое событие сохраняется в отдельный файл. Но как правило, в больших системах, требовательных к параллелизму и масштабируемости, используются более надежные способы хранения.

Журнал событий (event log) — очень распространенный паттерн, используемый совместно с системами обмена сообщениями (Message broker, Message-oriented middleware) и системами обработки потоков событий. Брокер сообщений, используемый как журнал событий, при необходимости может хранить всю историю сообщений.

Реляционные и документные модели обычно фокусируются на моделировании сущностей. В таких моделях текущее состояние легко получить, прочитав одну или несколько строк или документов. Стоит отметить, что Event Sourcing и реляционная модель не исключают друг друга. Event Sourcing-системы часто включают в себя и то и другое. Ключевое отличие Event Sourcing заключается в том, что к хранилищу сущностей уже не относятся как к исходным данным. Его можно заменить или перестроить через повторную обработку журнала событий.

В более сложных Event Sourcing-системах должны присутствовать производные хранилища состояния для эффективных запросов на чтение, так как получение текущего состояния через обработку всего журнала событий со временем может перестать масштабироваться. И реляционные, и документные БД могут использоваться и как журнал событий и как хранилище производных сущностей, через которые можно быстро получить текущее состояние. Фактически такое разделение задач представляет собой CQRS (Command Query Responsibility Segregation, разделение ответственности на команды и запросы). Все запросы направляются в производное хранилище, что позволяет оптимизировать его независимо от операций записи.

Помимо технической части есть и другие моменты, на которые стоит обратить внимание.

Потенциальные проблемы Event Sourcing


Несмотря на преимущества Event Sourcing, у него есть и недостатки.

Самые большие сложности обычно связаны с мышлением разработчиков. Разработчики должны выйти за рамки обычных CRUD-приложений и хранилищ сущностей. Теперь основной концепцией должны стать события.

При Event Sourcing много сил тратится на моделирование событий. После записи событий в журнал они должны считаться неизменными, иначе, и история и состояние могут быть повреждены или искажены. Журнал событий — это исходные данные, а это значит, что необходимо очень внимательно следить за тем, чтобы они содержали всю информацию, необходимую для получения полного состояния системы на определенный момент времени. Также необходимо учитывать, что события могут интерпретироваться повторно, поскольку система (и бизнес, который она представляет) со временем изменяются. И не надо забывать про ошибочные и подозрительные события с корректной обработкой валидации данных.

Для простых моделей предметных областей такое изменение мышления может быть довольно легким, но для более сложных может стать проблемой (особенно с большим количеством зависимостей и отношений между сущностями). Могут возникнуть сложности интеграции с внешними системами, которые не предоставляют данные на определенный момент времени.

Event Sourcing может хорошо работать в больших системах, так как паттерн «журнал событий» естественным образом масштабируется горизонтально. Например, журнал событий одной сущности необязательно должен физически находиться вместе с журналом событий другой сущности. Однако, такая легкость масштабирования приводит к дополнительным проблемам в виде асинхронной обработки и согласования данных в конечном счете (eventually consistent). Команды на изменение состояния могут приходить на любой узел, после чего системе необходимо определить, какие узлы отвечают за соответствующие сущности и направить команду на эти узлы, после чего обработать команду, а затем реплицировать сгенерированные события на другие узлы, где хранятся журналы событий. И только после завершения этого процесса новое событие становится доступным как часть состояния системы. Таким образом, Event Sourcing фактически требует, чтобы обработка команд была отделена от запроса состояния, то есть CQRS.

Поэтому Event Sourcing-системам необходимо учитывать промежуток времени между выдачей команды и получением уведомления об успешной записи события в журнал. Состояние системы, которое пользователи видят в это время, может быть «неправильным». Или, точнее, немного устаревшим. Для уменьшения влияния этого фактора необходимо его учитывать при проектировании интерфейса пользователя и в других компонентах. Также необходима правильная обработка ситуаций, когда команда завершается ошибкой, отменяется в процессе выполнения или одно событие заменяется более новым при корректировке данных.

Еще одна проблема возникнет, когда со временем накопятся события и с ними нужно будет работать. Одно дело только записывать их после обработки, другое — работать со всей историей. Без этого функционала журнал событий полностью теряет свою ценность. Особенно это актуально для восстановления после сбоя или при миграциях производных хранилищ, когда для актуализации данных может потребоваться повторная обработка всех событий. Для систем с большим количеством событий повторная обработка всего журнала может превысить допустимое время восстановления. Здесь могут помочь периодические снимки состояния системы (snapshot), чтобы можно было начать восстановление с более позднего исправного состояния.

Также необходимо учитывать структуру событий. Структура событий может изменяться с течением времени. Может изменяться набор полей. Возможны ситуации, когда старые события должны быть обработаны текущей бизнес-логикой. И наличие расширяемой схемы событий поможет в будущем при необходимости отличать новые события от старых. Периодические снимки также помогают отделить серьезные изменения структуры событий.

Выводы


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

Однако, как и в случае с любым серьезным архитектурным решением, необходимо проявлять осторожность и убедиться, что оно подходит для вашей ситуации. Ограничения, связанные со сложностью предметной области, требованиями к согласованности и доступности данных, а также увеличение объема хранимых данных и масштабируемость в долгосрочной перспективе — все это необходимо учитывать (и это ни в коем случае не исчерпывающий список). Не менее важно уделять внимание разработчикам, которые будут разрабатывать и поддерживать такую ​​систему на протяжении всего ее жизненного цикла.

И напоследок, не забывайте самый важный принцип программной инженерии — стремиться к тому, чтобы все было как можно проще (принцип KISS).


Читать первую часть

OTUS. Онлайн-образование
Цифровые навыки от ведущих экспертов

Комментарии 0

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое