BI Consult Desktop Logo BI Consult Mobile Logo
  • Russian BI Исследование российских bi
  • Перейти на Fine BI
  • Контакты
  • +7 812 334-08-01
    +7 499 608-13-06
  • Отправить сообщение
  • Главная
  • Продукты Эксперт-BI
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Сельское хозяйство
    • Энергетика
    • FMCG
    • Девелоперы
    • Маркетплейсы
    • Пищевая промышленность
    • Фармацевтика
    • Построение Data Platform
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и FP&A
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • IBP
    • ИТ (CIO)
    • Закупки
  • Платформы
    • Системы бизнес-анализа (BI)
    • Интегрированное бизнес-планирование (IBP)
    • Хранилища данных (DWH / Lakehouse)
    • Каталоги данных (Data Catalog)
    • Системы ETL и ELT
    • AI / Исскуственный интеллект
    • Шина данных (ESB)
    • Система управления мастер-данными (MDM)
    • Семантический слой
  • Услуги
    • Переход на отечественные BI и DWH системы
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений и DWH
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Курсы
    • Учебный курс Информационная грамотность (Data Literacy)
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Greenplum
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt (Data Build Tool)
  • Компания
    • Руководство
    • Новости
    • Клиенты
    • Карьера
    • Скачать
    • Контакты

BI

  • FineBI
  • FineReport
  • FineDataLink
  • FineChatBI (FineAI)
  • Коннекторы данных из 1С в BI
  • Airflow / Nifi
  • Visiology
  • PIX BI
  • Modus BI
  • Yandex.DataLens
  • Open-source BI: Superset/Metabase
  • Luxms BI
  • AW BI + Alpha BI
  • FlyBI + Форсайт. Аналитическая Платформа
  • Loginom
  • Триафлай
  • AI / Исскуственный интеллект
  • Optimacros
  • Навигатор BI
  • Семантический слой

СУБД

  • Arenadata
  • ClickHouse
  • Greenplum
  • Postgres Professional
  • TData

Другое

  • Построение Data Platform
    • Аналитическое хранилище данных
    • Data Lake и Data Engineering
    • Подробнее про Data Lake
    • Внедрение Lakehouse
      • Apache Doris
      • StarRocks
      • Trino
    • Миграция витрин из пропиетарных DWH на новый стек
    • Учебный курс "Современная архитектура хранилища данных"
Главная » Курсы по системам бизнес-анализа и методологии » Учебный курс для системных аналитиков » Модуль 3.5. Событийная модель и доменная интеграция

Модуль 3.5. Событийная модель и доменная интеграция

Темы: события домена, схемы, совместная эволюция, outbox, гарантированная доставка. Артефакт: событийный каталог. Практика: разработать 5 доменных событий.

 

Системный аналитик (SA) задаёт общий язык фактов между системами: как выглядит событие, какие поля обязательны, как оно меняется со временем, какие гарантии доставки и порядка соблюдаются. В этом модуле вы получите:

  • чек-лист проектирования событий;
  • правила эволюции схем (совместимость, версии);
  • рабочие конфигурации outbox + CDC;
  • практикум: 5 событий e-commerce-домена, готовые схемы и рекомендации по ключам/партициям.

 

Что такое доменное событие (и что им не является)

  • Событие домена — необратимый факт, который уже случился в домене: OrderCreated, PaymentCaptured, RefundCompleted.
  • Не события: команды (ReserveStock), логи трассировки, технические метрики. Команда адресна и просит «сделать», событие — факт «случилось».

 

Принципы событийной модели

  1. Правда и минимум: только факты и минимальный набор атрибутов (без PII/секретов).
  2. Детерминированные ключи: eventId (UUID), aggregateId (например, orderId), correlationId/causationId.
  3. Повторяемость: допускаем повторы и перестановки → консъюмеры обязаны быть идемпотентными.
  4. Порядок/партиционирование: порядок гарантирован только внутри ключа партиции (orderId), между агрегатами порядка нет.

 

Конверт (envelope) события: стандарт для проекта

Рекомендуемый каркас (не payload, а обёртка). Любой продьюсер и консъюмер должны его понимать:

{
  "eventId": "uuid",
  "type": "payment.captured.v1",
  "occurredAt": "2025-08-20T12:34:56Z",
  "producer": "payments-service",
  "correlationId": "uuid-or-traceparent",
  "causationId": "uuid-of-parent-event-or-command",
  "aggregateType": "Order",
  "aggregateId": "uuid-of-order",
  "schemaVersion": "1.0.0",
  "payload": { /* доменные поля события */ }
}

 

Почему так:

  • eventId — основа дедупликации у подписчиков;
  • correlationId/causationId — сквозная трассировка бизнес-потока;
  • aggregateId — partition key (гарантия локального порядка).

 

Схемы сообщений и эволюция (совместная)

Схема (Avro/Protobuf/JSON Schema)

  • Для шины (Kafka/NATS/Kinesis) — предпочтительны Avro/Proto + Schema Registry.
  • Схема описывает payload; envelope можно фиксировать отдельно.

 

Политики совместимости (рекомендуем)

  • Backward как дефолт (новая схема читает старые данные).
  • Full (backward+forward) — если много живых потребителей с разными версиями.
  • Запрещаем: переименование/удаление поля без MAJOR; смену типа; изменение семантики.

 

Эволюция без боли

  • Новые поля — optional с дефолтом;
  • Устаревшие — помечаем deprecated, оставляем N релизов;
  • Ломающие — новое имя события: payment.captured.v2 и параллельная публикация в течение окна миграции.

 

Гарантированная доставка на практике

  • В реальных EDA достигается at-least-once + идемпотентные консъюмеры → «effect exactly-once».
  • DLQ (dead-letter queue): правим яд, не меняем данные молча.
  • Повторы/перестановки: консъюмер хранит processed_event(eventId, processedAt) с TTL ≥ retention.

 

Метрики прочности

  • consumer_lag, dlq_size, event_dup_rate, out_of_order_count, publish_latency_p95.

 

Outbox + CDC — лекарство от dual-write

Проблема

Обновили БД и отправили событие — любой сбой между операциями создаст рассинхрон. Нужна атомарность.

 

Шаблон Outbox

  1. В одной транзакции с бизнес-записью пишем строку в outbox.
  2. Фоновый паблишер (или CDC) читает outbox и публикует в шину.
  3. Продьюсер помечает сообщение как отправленное и/или удаляет/компактиует.

 

DDL-эскиз (PostgreSQL)

CREATE TABLE outbox_events (
  id              uuid PRIMARY KEY,
  aggregate_type  text NOT NULL,
  aggregate_id    text NOT NULL,
  type            text NOT NULL, -- e.g. payment.captured.v1
  payload         jsonb NOT NULL,
  headers         jsonb NOT NULL,
  occurred_at     timestamptz NOT NULL DEFAULT now(),
  published_at    timestamptz,
  attempts        int NOT NULL DEFAULT 0
);
CREATE INDEX ON outbox_events (published_at) WHERE published_at IS NULL;

 

Паблишер:

  • читает батч непубликованных;
  • публикует (с ключом aggregate_id);
  • при успехе проставляет published_at;
  • при ошибке — увеличивает attempts и откладывает по экспоненте;
  • яд «ядовитых» — в DLQ + тикет.

 

CDC-вариант: Debezium/Streams → снижает накладные расходы, повышает устойчивость.

 

Паттерны порядка и дедупликации

  • Partition key = бизнес-ключ агрегата (orderId, customerId).
  • В payload держим монотонный version/sequence объекта → консъюмер игнорирует устаревшие (seq < current).
  • Таблица/кэш processed_event(eventId) (TTL 7–30 дней) → идемпотентность при повторах.

 

Безопасность и приватность

  • В событиях нет PII/секретов — только идентификаторы.
  • Если нужно передать контекст (валюта/сумма) — только то, что безопасно и не под NDA.
  • Подписывайте вебхуки (HMAC/MTLS), ограничивайте ACL публикации/подписки; шифруйте at rest/in flight.

 

Наблюдаемость событий

  • В каждый publish — correlationId, causationId, метки schemaVersion.
  • Дашборды: publish_latency_p95, topic_rps, consumer_lag, dlq_size, dedup_hits, out_of_order.
  • Логи: структурированные (JSON), без PII.

 

Категории событий (как говорить с бизнесом)

  • События жизненного цикла (OrderCreated, OrderPaid, OrderShipped).
  • События изменения атрибутов (CustomerAddressChanged).
  • События компенсаций/ошибок (RefundFailed).
  • Снимки/сводки (редко): OrderSnapshotCreated — для поздних подписчиков.

 

Практические примеры: 5 доменных событий

Для домена «Заказы–Платежи–Возвраты». Покажу Avro-схемы payload, AsyncAPI-фрагменты и рекомендации по партициям.

 

order.created.v1

Назначение: факт создания заказа.
Partition key: orderId.
Потребители: склад/логистика, аналитика, email.

Avro payload (order-created.v1.avsc):
{
  "type":"record","name":"OrderCreated","namespace":"events.orders.v1",
  "fields":[
    {"name":"orderId","type":"string"},
    {"name":"customerId","type":"string"},
    {"name":"currency","type":"string"},
    {"name":"totalAmount","type":"string"},
    {"name":"createdAt","type":{"type":"long","logicalType":"timestamp-millis"}},
    {"name":"items","type":{"type":"array","items":{
      "name":"Item","type":"record","fields":[
        {"name":"productId","type":"string"},
        {"name":"qty","type":"int"},
        {"name":"price","type":"string"}
      ]}}}
  ]
}

 

payment.captured.v1

Назначение: деньги фактически списаны.
Partition key: orderId (сохранить локальный порядок заказа).
Потребители: отгрузка, уведомления, бухгалтерия.

Avro payload (payment-captured.v1.avsc):
{
  "type":"record","name":"PaymentCaptured","namespace":"events.payments.v1",
  "fields":[
    {"name":"paymentId","type":"string"},
    {"name":"orderId","type":"string"},
    {"name":"amount","type":"string"},
    {"name":"currency","type":"string"},
    {"name":"capturedAt","type":{"type":"long","logicalType":"timestamp-millis"}},
    {"name":"method","type":["null",{"type":"enum","name":"Method","symbols":["CARD","APPLE_PAY","GOOGLE_PAY"]}], "default": null}
  ]
}

 

order.shipped.v1

Назначение: заказ передан в доставку.
Partition key: orderId.
Потребители: трекинг, E-mail/SMS, аналитика.

Avro payload (order-shipped.v1.avsc):
{
  "type":"record","name":"OrderShipped","namespace":"events.orders.v1",
  "fields":[
    {"name":"orderId","type":"string"},
    {"name":"shipmentId","type":"string"},
    {"name":"carrier","type":"string"},
    {"name":"trackingNumber","type":"string"},
    {"name":"shippedAt","type":{"type":"long","logicalType":"timestamp-millis"}}
  ]
}

 

refund.completed.v1

Назначение: возврат завершён.
Partition key: paymentId (или orderId, если все потребители привязаны к заказу).
Потребители: биллинг, аналитика, антифрод.

Avro payload (refund-completed.v1.avsc):
{
  "type":"record","name":"RefundCompleted","namespace":"events.refunds.v1",
  "fields":[
    {"name":"refundId","type":"string"},
    {"name":"paymentId","type":"string"},
    {"name":"orderId","type":"string"},
    {"name":"amount","type":"string"},
    {"name":"currency","type":"string"},
    {"name":"completedAt","type":{"type":"long","logicalType":"timestamp-millis"}},
    {"name":"reason","type":["null",{"type":"enum","name":"RefundReason","symbols":["CUSTOMER_REQUEST","DUPLICATE","FRAUD_SUSPECTED"]}],"default":null}
  ]
}

 

ustomer.address.changed.v1

Назначение: у клиента сменился адрес (для аналитики/антифрода/маркетинга).
Partition key: customerId.
Потребители: CRM/DWH.

Avro payload (customer-address-changed.v1.avsc):
{
  "type":"record","name":"CustomerAddressChanged","namespace":"events.customers.v1",
  "fields":[
    {"name":"customerId","type":"string"},
    {"name":"addressId","type":"string"},
    {"name":"changedAt","type":{"type":"long","logicalType":"timestamp-millis"}},
    {"name":"country","type":"string"},
    {"name":"city","type":"string"}
  ]
}

 

Заметьте: никаких PII (улица/дом/квартира) в событии — только агрегированные поля.

 

10.x. AsyncAPI-фрагмент (один топик в качестве примера)

asyncapi: '3.0.0'
info: { title: Commerce Events, version: 1.0.0 }
channels:
  payments.captured.v1:
    address: payments.captured.v1
    messages:
      PaymentCaptured:
        $ref: '#/components/messages/PaymentCaptured'
components:
  messages:
    PaymentCaptured:
      name: PaymentCaptured
      payload:
        $ref: 'avro://events.payments.v1.PaymentCaptured'
      correlationId:
        location: "$message.header#/correlationId"
      headers:
        type: object
        properties:
          eventId: { type: string, format: uuid }
          correlationId: { type: string }
          causationId: { type: string }
          aggregateId: { type: string }
  servers:
    prod: { host: kafka01:9092, protocol: kafka }

 

Каталог событий (артефакт)

Шаблон страницы каталога: каждое событие = карточка.

# Event Catalog vX.Y.Z
## payments.captured.v1
Описание: Деньги списаны.
Producers: payments-service
Consumers: shipping, email, billing
Key (partition): orderId
Ordering: гарантируется внутри orderId
Semantics: at-least-once, idempotent required
Schema: avro://events.payments.v1.PaymentCaptured (compat: backward)
Retention: 7 days (compact: off)
Security: ACL (produce: payments-svc, consume: shipping|email|billing), no PII
Observability: metrics publish_latency_p95, topic_rps, consumer_lag; log fields eventId/correlationId
Change policy: N/N-1, deprecate window 90 days

 

Рядом храните:

  • схемы (Avro/Proto) и AsyncAPI;
  • пример payload;
  • матрицу зависимости (кто слушает);
  • политику версионирования и окно депрекейта.

 

Тестирование событий

  • Contract tests: consumer-driven (Pact/Avro-compat), гейт в CI.
  • Golden cases: набор примеров payload (валид/невалид, min/max).
  • Replays: возможность поднять консюмера и прокрутить от offset (staging topic).
  • Chaos: дубликаты, перестановки, «ядовитые» сообщения, задержки.

 

Типовые риски и как их гасить

  1. Dual-write (рассинхрон БД и шины). → Outbox + CDC.
  2. Ломающие изменения схем. → Registry + compat + open-review, параллельная публикация v1/v2.
  3. PII в событиях. → Политика «минимум полей», DLP-сканы, ревью схем.
  4. Нет идемпотентности у консюмера. → Таблица processed_event, естественные ключи, seq/version.
  5. Потеря порядка между агрегатами. → Коммуникация ожиданий: порядок только внутри partition key.
  6. DLQ без обработки. → Авто-тикеты, SLO по разбору DLQ.
  7. Бессрочные ретраи. → Классификация ошибок, лимиты попыток, backoff + jitter, quarantine-topic.

 

Вопрос–Ответ

Q: Почему «exactly-once» — это миф?
A: В распределённых системах нет абсолютной гарантии; достигаем эффект exactly-once через at-least-once + идемпотентность + дедуп.

 

Q: Как выбирать partition key?
A: По агрегату, для которого важен порядок (orderId, customerId). Если важно пересечение нескольких — пересмотрите дизайн (саги, согласования).

 

Q: Можно ли публиковать состояние (снимок) вместо события?
A: Да, для поздних подписчиков — как дополнение (compact topic). Но «истинные» факты — события.

 

Q: Что делать, если консъюмер «отстаёт»?
A: Масштабируйте группу (больше партиций/инстансов), оптимизируйте обработку, включите backpressure, следите за consumer_lag.

 

Q: Как долго хранить события?
A: Зависят от кейсов: 7–30 дней для интеграции, дольше — для аналитики/реигрывания. Важно согласовать с безопасностью и GDPR.

 

Практика: разработать 5 доменных событий (90–120 мин)

Задание: для вашего проекта опишите 5 событий (как в §10):

  1. Выберите имена и версии: order.created.v1, payment.captured.v1, order.shipped.v1, refund.completed.v1, customer.address.changed.v1.
  2. Определите partition key и ожидания порядка.
  3. Опишите Avro-схемы payload и envelope.
  4. Заполните карточки Событийного каталога (producers/consumers, retention, compat, security).
  5. Подготовьте golden payloads (валид/границы/невалид).
  6. Пропишите стратегию эволюции (какие поля могут добавляться, окна депрекейта).
  7. Сформируйте RTM-связки: UC/FR → события → подписчики → метрики.

 

Критерии зачёта:

  • События минимальны и безопасны (без PII).
  • Есть явный partition key и позиция по порядку.
  • Схемы совместимы (backward), определена политика версий.
  • Каталог заполнен (SLO, ACL, retention, observability).
  • Идемпотентность консъюмеров предусмотрена (eventId/seq).

 

Шпаргалка (коротко)

  • Событие = факт, команда = инструкция.
  • Порядок только внутри partition key.
  • At-least-once + идемпотентность → практический exactly-once.
  • Outbox + CDC — стандарт, а не опция.
  • Schema Registry + compat; новые поля — optional.
  • Никаких PII в событиях.
  • Каталог событий — обязательный артефакт: кто публикует/слушает, ключ, версия, SLO, ACL, retention.
  • Метрики и логи: eventId, correlationId, latency, lag, DLQ.

 

 

 

Узнать стоимость решенияЗапросить видео презентацию

← Предыдущая статья
Модуль 3.4. API-дизайн: REST / GraphQL / gRPC
Следующая статья →
Модуль 3.6. SQL для системного аналитика

Решения

Анализировать ФинансыУвеличивайте ПродажиОптимальный Склад и ЛогистикаМаркетинговые Метрики

Клиенты
  • ООО «Ай Пи Ти Групп» (IPT Group) — многопрофильный консалтинговый холдинг, специализирующийся на юридическом и финансовом сопровождении бизнеса. IPT Group занимает высокие позиции в профессиональных рейтингах, входит в ТОП-30 лучших юридических компаний России по версии «Право.ru-300», Global Law Experts и др.

  • «Балтийский лизинг» — первая компания в России, получившая лицензию № 0001 от Министерства экономики РФ на лизинговую деятельность, лицензия зарегистрирована 2 сентября 1996 года. «Балтийский лизинг» работает на российском рынке 33 года: компания представлена 79 филиалами по всей стране, сегодня в штате более 1300 сотрудников. За последние десять лет компания профинансировала имущество для 80 000 клиентов.

  • Русклимат
    Русклимат — международный торгово-производственный холдинг, концентрирующий опыт ведущих мировых производителей индустрии климата, мощный потенциал конструкторских бюро и лабораторий индустриального дизайна.
     
    Компания образована в 1996 году. За более чем двадцатилетнюю историю Русклимат прошел путь от локальной компании до мощной вертикально-интегрированной многопрофильной структуры.
     
  • ИНВИТРО
    ИНВИТРО – крупнейшая частная медицинская компания в России, специализирующаяся на лабораторной диагностике и оказании других медицинских услуг.
     
    ИНВИТРО располагает 9 самыми современными лабораторными комплексами и крупнейшей в Восточной Европе сетью более чем из 900 медицинских офисов. Страны присутствия — Россия, Украина, Казахстан, Беларусь.
     
  • Решения
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Энергетика
    • Фармацевтика
  • Услуги
    • Переход на отечественные BI и DWH
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Техническая поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Платформы
    • FineBI
    • FineReport
    • FineDataLink
    • Коннекторы данных из 1С в BI
    • Airflow + NiFi
    • Visiology
    • Luxms BI
    • Modus BI
    • PIX BI
    • Arenadata
    • ClickHouse
    • Greenplum
    • Postgres Professional
    • Open-source BI: Superset/Metabase
    • Loginom
    • Yandex.DataLens
    • AI / Исскуственный интеллект
    • Optimacros
    • Шины данных
  • Курсы
    • Учебный курс Информационная грамотность
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt
  • Функциональные решения
    • Создание Data Lake
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и прогнозная аналитика
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • Сквозная аналитика
  • Компания
    • О нас
    • Руководство
    • Новости
    • Клиенты
    • Скачать
    • Контакты
    • Политика конфиденциальности
RutubeVkontakteLinkedInYouTube
ООО "Би Ай Консалт",
ИНН: 7811437757,
ОГРН: 1097847154184
199178, Россия,
Санкт-Петербург,
6-ая линия В.О., Д. 63, 4 этаж
Тел: +7 (812) 334-08-01
Тел: +7 (499) 608-13-06
E-mail: info@biconsult.ru

 

 

 

 

 

×

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