System Design Space
Граф знанийНастройки

Обновлено: 1 мая 2026 г. в 08:17

Событийно-ориентированная архитектура: Event Sourcing, CQRS, Saga

средний

Практический разбор событийной архитектуры: как проектировать контракты событий, где действительно нужны Event Sourcing, CQRS и Saga и как переживать лаги, повторы и DLQ в асинхронных потоках.

Событийная архитектура ценна не абстрактным обещанием слабой связности, а тем, что позволяет разнести принятие решения, публикацию факта и реакцию зависимых сервисов во времени.

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

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

Практическая польза главы

Контракты событий

Проектируйте события как устойчивые бизнес-факты с совместимой эволюцией схем, а не как случайные транспортные пакеты.

Координация шагов

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

Повторы и DLQ

Планируйте повторное воспроизведение, DLQ и идемпотентность обработчиков так, чтобы сбой не превращался в потерю данных.

Аргументация выбора

Объясняйте, когда события действительно снижают связанность, а когда они только добавляют лаги и операционную сложность.

Источник

Martin Fowler: Event Sourcing

Классический текст о том, зачем хранить историю состояния через события и где этот подход действительно полезен.

Открыть материал

полезна не потому, что один брокер сам по себе автоматически делает систему гибкой, а потому, что позволяет разнести момент принятия решения и момент реакции на него. Эта свобода даёт масштабируемость и слабую связность, но требует аккуратно проектировать события, контракты и восстановление после сбоев.

Базовые принципы событийной архитектуры

В этой главе мы отдельно разберём , и . Это не обязательный комплект на все случаи, а три разных инструмента, которые по-разному помогают управлять историей изменений, нагрузкой на чтение и запись и длинными бизнес-процессами.

Для этого полезно заранее договориться, что такое , как устроены и , когда требуется и какую роль играют , и , и где действительно нужен . Если система живёт с , доставкой , , , и , то эти решения нужно принимать отдельно внутри каждого , а не размазывать один и тот же шаблон на всю систему.

Событие фиксирует факт

Событие описывает то, что уже произошло в домене, и не должно меняться задним числом.

Асинхронность разрывает связность

Производители и потребители могут развиваться отдельно, если контракт события остаётся стабильным.

Согласование приходит не мгновенно

Между записью и итоговым видом данных часто есть лаг, который продукт и API должны переживать предсказуемо.

Визуализация потоков данных

Ниже показаны три характерных сценария: базовый событийный поток, разделение чтения и записи в CQRS и координация шагов в паттерне Saga.

Анимации потоков данных

Каждую схему можно запускать отдельно кнопкой «Старт».

Базовый поток событий

1

API команд

Принимает бизнес-команду

2

Доменный агрегат

Проверяет инварианты и принимает решение

3

Хранилище событий

Последовательно записывает события

4

Брокер или журнал

Раздаёт события потребителям

5

Потребители

Строят проекции, интеграции и побочные действия

CQRS: путь записи и путь чтения

Обе ветки показаны параллельно и запускаются независимо.

Путь записи

1

Клиент

Отправляет команду POST или PUT

2

Модель команд

Применяет правила и инварианты

3

Поток событий

Фиксирует факты домена

4

Проектор

Обновляет модель чтения

Путь чтения

1

Клиент

Отправляет запрос GET

2

API чтения

Отдаёт только данные для чтения

3

Модель чтения

Хранит денормализованную проекцию

Saga: стили координации

Отдельный координатор решает, какой шаг запускать дальше и когда начинать компенсации.

Все ключевые команды и решения проходят через одного координатора.

Сервис заказов

OrderCreated

Оркестратор
Оркестратор

ReserveFunds

Платёжный сервис
Платёжный сервис

PaymentReserved

Оркестратор
Оркестратор

ReserveStock

Сервис склада
Сервис склада

InventoryReserved

Оркестратор
Оркестратор

CreateShipment

Сервис доставки
Сервис доставки

ShipmentCreated

Оркестратор
Оркестратор

OrderCompleted

Сервис заказов
Ключевая идея: один координатор принимает решения и управляет вызовами сервисов.

Связанная глава

Microservice Patterns

Отдельная глава про интеграционные паттерны, Saga и границы распределённых транзакций.

Открыть главу

Event Sourcing, CQRS и паттерн Saga

Event Sourcing

Состояние восстанавливается из последовательности событий, а не хранится только как последнее значение.

Когда применять

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

Компромиссы

  • Сложнее эволюция схемы событий и миграции старой истории.
  • Нужны снимки состояния и стратегия повторного воспроизведения, чтобы не замедлить систему.

CQRS

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

Когда применять

  • Нагрузка на чтение и запись заметно различается.
  • Нужны отдельные проекции, оптимизированные под быстрые чтения.
  • Система выросла настолько, что пути чтения и записи выгодно масштабировать независимо.

Компромиссы

  • Увеличиваются операционная сложность и число компонентов.
  • Модель чтения часто сходится с путём записи не мгновенно, а с лагом.

Saga

Распределённая операция раскладывается на локальные шаги и компенсирующие действия вместо одной общей транзакции.

Когда применять

  • Одна бизнес-операция затрагивает несколько сервисов или хранилищ.
  • 2PC недоступен или слишком дорог по задержке и связанности.
  • Нужно управляемо откатывать частично завершённый процесс через компенсации.

Компромиссы

  • Каждый шаг и каждая компенсация должны переживать повторы без двойного эффекта.
  • Отладка долгоживущих и частично завершённых процессов становится сложнее.

Связанная книга

Software Architecture: The Hard Parts

Подробный разбор инженерных компромиссов, распределённых процессов и практики применения Saga.

Открыть главу

Saga: стили координации

делает процесс прозрачнее и централизует решения, а сильнее ослабляет связанность, но сложнее для трассировки и отладки.

Хореография

Сервисы подписываются на события и сами запускают следующий шаг без центрального координатора.

Плюсы

  • Слабее связность между сервисами
  • Нет единой управляющей точки, которая станет узким местом

Риски

  • Сложнее проследить весь путь операции целиком
  • Легко получить хаотичную сеть событий без явных границ

Оркестрация

Отдельный координатор явно решает, какой шаг выполнять дальше и когда запускать компенсации.

Плюсы

  • Проще наблюдать процесс целиком
  • Легче проверять бизнес-логику и правила переходов

Риски

  • Появляется центральная точка сложности
  • Контур оркестрации нужно отдельно масштабировать и защищать

Как выбирать паттерн

ЗадачаЧто выбратьПочему
Нужна полная история изменений и восстановление состоянияEvent SourcingИстория становится первичными данными, а не побочным журналом.
К чтению и записи предъявляются разные требования по уровню сервиса и профилю нагрузкиCQRSМожно отдельно оптимизировать и масштабировать путь чтения и путь записи.
Одна операция охватывает несколько сервисов без общей транзакцииSagaЛокальные шаги и компенсации дают контролируемое завершение процесса.
Система остаётся простой CRUD-моделью без сложных интеграцийНе навязывать событийную архитектуруОперационная сложность может оказаться выше реальной бизнес-пользы.

Частые ошибки

  • Внедрять Event Sourcing, CQRS и Saga одновременно без явной проблемы, которую нужно решить.
  • Публиковать в события технический шум вместо фактов предметной области.
  • Не проектировать идемпотентность обработчиков при доставке как минимум один раз.
  • Оставлять эволюцию схемы событий без политики обратной совместимости.
  • Не следить за DLQ, лагом обработки, скоростью роста дублей и временем завершения Saga.

Связанная глава

Паттерны отказоустойчивости

DLQ дополняет повторы, тайм-ауты и изоляцию сбоев в контурах асинхронной обработки.

Открыть главу

Очередь ошибочных сообщений (DLQ)

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

Когда отправлять в DLQ

Когда сообщение исчерпало лимит повторов, нарушает контракт события или стабильно падает из-за данных.

Что сохранять

Идентификатор сообщения, число попыток, последнюю ошибку, источник, время сбоя и ссылку на полезную нагрузку.

Что делать дальше

Разобрать причину, исправить её и вернуть сообщения в основной поток с контролем скорости и идемпотентности.

Практический чеклист для DLQ

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

Проверки перед внедрением

1. Зафиксируйте контракты событий и политику версионирования.
2. Обеспечьте идемпотентность и у производителей, и у обработчиков.
3. Настройте DLQ, правила повторов и процесс возврата сообщений.
4. Следите за лагом обработки, временем воспроизведения и завершением Saga.

Практический подход: начните с одного-двух критичных процессов, сначала зафиксируйте контракт, наблюдаемость и правила повторов, и только потом масштабируйте событийную модель на остальные контуры системы.

Сначала контракт и операционная дисциплинапотом расширение событийной архитектуры.

Связанные главы

Чтобы отмечать прохождение, включи трекинг в Настройки