GH GambleHub

Event-Driven ядро

Що таке Event-Driven ядро

Event-Driven ядро (EDC) - це «хребет» архітектури, в якому бізнес-факти фіксуються і поширюються як незмінні події, а інша функціональність (читання, інтеграції, аналітика, кеші, нотифікації) будується поверх потоку цих подій. Ядро задає контракт подій, правила доставки та інваріанти порядку/ідемпотентності, забезпечуючи слабку зв'язність і масштабованість.

Ключова ідея: спочатку записати факт (ядро), а потім незалежно збагачувати і проектувати його в потрібні моделі. Це зменшує зв'язність і підвищує стійкість до часткових збоїв.

Цілі та властивості EDC

Істинність фактів: кожна подія - незмінний запис «що сталося».
Слабка зв'язність: продюсери не знають споживачів; розширення системи - додаванням передплатників.
Масштабування: горизонтальне зростання по партіях/топіках, незалежні споживачі.
Спостережуваність і аудит: наскрізні ідентифікатори, відтворюваність, ретенції та репрогравання.
Керована еволюція: версії схем, сумісність, deprecation.

Архітектурні компоненти

1. Шина/брокер подій: Kafka/NATS/Pulsar/SNS + SQS - канали, партії, ретенції.
2. Реєстр схем: JSON Schema/Avro/Protobuf для сумісності та еволюції.
3. Outbox/CDC-контур: атомарна фіксація факту + публікація без «подвійного запису».
4. Проекції/читання (CQRS): матеріалізовані уявлення для швидких запитів.
5. Саги/оркестрація: координація довгоживучих процесів через події/команди.
6. Збагачення: окремі топіки'.enriched '/' .derived'без впливу на критичний шлях.
7. Обсервабіліті: трасування, логування, метрики по подіям і лагам.

Модель подій

Типи подій

Domain Events: бізнес-факти ('payment. authorized`, `kyc. approved`).
Integration Events: орієнтовані на зовнішні системи (стабільні, повільно змінюються).
Change Data Capture (CDC): технічні зміни запису (використовуйте для міграцій/інтеграцій).
Audit/Telemetry: дії акторів, безпека, SLA.

Обов'язкові атрибути (ядро)

json
{
"event_id": "uuid",
"event_type": "payment. authorized. v1",
"occurred_at": "2025-10-31T11:34:52Z",
"producer": "payments-service",
"subject": { "type": "payment", "id": "pay_123" },
"payload": { "amount": 1000, "currency": "EUR", "method": "card" },
"schema_version": 1,
"trace_id": "abc123",
"partition_key": "pay_123"
}

Рекомендації: 'event _ id'глобально унікальний,'partition _ key'задає порядок для сутності,'trace _ id'забезпечує кореляцію.

Семантика доставки та ідемпотентність

At-least-once (за замовчуванням у багатьох брокерів): споживачі зобов'язані бути ідемпотентними.
At-most-once: прийнятно лише для другорядних телеметрій.
Exactly-once: досягається на рівні потоку і сховища через транзакції/ідемпотентні ключі/лейки (дорожче, потрібна вагома причина).

Шаблон ідемпотентності споживача

Дедуп-таблиця по'event _ id '/' (event_id, consumer_id)'з TTL ≥ ретенції топіка.
Upsert замість insert; версіонування проекцій за «sequence »/« occurred _ at».
Операції в рамках транзакції: позначка «бачив» + зміна стану.

Порядок і партіонування

Гарантований порядок у межах партії.
Вибирайте'partition _ key'так, щоб всі події однієї агрегат-сутності потрапляли в одну партію ('user _ id','payment _ id').
Уникайте «гарячих ключів»: хеш з сіллю/під-ключі, якщо потрібно розподілити навантаження.

Схеми та еволюція

Additive-first: нові опціональні поля, заборона на зміну типів/семантики без major-версії.
Сумісність: BACKWARD/FORWARD в реєстрі схем; CI блокує несумісні зміни.
Іменування: `domain. action. v{major}` (`payment. authorized. v1`).
Міграції: публікуйте пари «v1» і «v2» паралельно, забезпечте подвійне випромінювання (dual-write через outbox), знімайте «v1» після переходу.

Outbox и CDC

Outbox (рекомендується для транзакційних сервісів)

1. В одній БД-транзакції: зберігаємо доменний запис і подію в outbox.
2. Фоновий паблішер читає outbox, публікує в брокер, позначає «відправлено».
3. Гарантії: немає «втрати» факту при падіннях, немає розсинхронізації.

CDC (Change Data Capture)

Підходить для існуючих систем/міграцій; джерело - лог реплікації БД.
Вимагає фільтрації/перекодування в доменні події (не транслюйте «сирі» таблиці зовні).

CQRS і проекції

Команди змінюють стан (часто синхронно), події - формують проекції (асинхронно).
Проекції розраховані на запити (пошук, списки, звіти), оновлюються передплатниками.
Тимчасова розсинхронізація - норма: показуйте стійкий UX («дані оновляться через кілька секунд»).

Саги: координація процесів

Оркестрація: один координатор посилає команди і чекає подій.
Хореографія: учасники реагують на події один одного (простіше, але вимагає дисципліни в контрактах).
Правила: чіткі компенсації і тайм-аути, повторювані кроки, ідемпотентні обробники.

Спостережуваність

Trace/Span: прокидайте'trace _ id '/' span _ id'через заголовки при породженні подій.
Метрики: лаг споживачів, швидкість публікації/споживання, dead-letter rate, частка дедуплікацій.
DLQ/parking lot: неуспішні повідомлення - в окремий топік з алертом; забезпечте переобробку.

Безпека та відповідність

Класифікація даних: ядро містить тільки необхідний мінімум PII/фінданих (модель зворотної піраміди), деталі - у збагаченнях.
Підпис/хеш критичних атрибутів, контроль цілісності.
Шифрування in-flight та at-rest, секціонування прав за темами/консюмерами (IAM/ACL).
Політики ретенції та права на забуття: чітко визначені для кожного топіка.

Продуктивність і стійкість

Backpressure: у споживачів - обмеження конкурентності, у брокера - квоти/ліміти.
Batch-обробка і компресія: групуйте записи для зниження накладних витрат.
Ретраї з джиттером і DLQ замість нескінченних спроб.
Rebalance-стійкість: зберігайте офсети транзакційно/зовні, прискорюйте холодний старт снапшотами.

Типові шаблони подій

Ядро платежів

`payment. initiated. v1` → `payment. authorized. v1` → `payment. captured. v1` → `payment. settled. v1`

Відмови: `payment. declined. v1`, `payment. refunded. v1`

Партіонування: `payment_id`

SLA: лаг ядра ≤ 2с p95; ідемпотентність споживачів обов'язкова.

КУС/верифікації

`kyc. started. v1` → `kyc. document. received. v1` → `kyc. approved. v1`/`kyc. rejected. v1`

PII - мінімально; деталі документа - в'kyc. enriched. v1'з обмеженим доступом.

Аудит/безпека

`audit. recorded. v1'з атрибутами'actor','subject','action','occurred _ at','trace _ id'.
Безперервна ретенція/архівування; підвищена цілісність (WORM-сховища).

Антипатерни

Fat Event: перевантажені payload'и без потреби, витоку PII.
Hidden RPC через події: очікування синхронних відповідей «тут і зараз».
Сирі CDC назовні: тісна зв'язність зі схемою БД.
Немає ідемпотентності у споживачів: дублі призводять до подвійних побічних ефектів.
Одна загальна топіка «на все»: конфлікт інтересів, проблемний порядок, складна еволюція.

Покрокове впровадження EDC

1. Картування домену: виділіть ключові агрегати і життєві цикли.
2. Каталог подій: назви, смисли, інваріанти, обов'язкові поля.
3. Схеми та реєстр: виберіть формат, увімкніть правила сумісності.
4. Outbox/CDC: для кожного продюсера визначте механізм публікації фактів.
5. Партіонування: виберіть ключі і оцініть гарячі ключі/перерозбиття.
6. Ідемпотентність: шаблон дедупа + транзакційність споживачів.
7. Проекції: визначте матеріалізовані моделі та SLA оновлення.
8. Обсервабіліті: трасування, лаги, DLQ, алерти.
9. Security/PII: класифікація даних, шифрування, ACL.
10. Гайд по еволюції: політика версій, депрекейт, dual-write для міграцій.

Чек-лист продакшену

  • У кожної події є'event _ id','trace _ id','occurred _ at','partition _ key'.
  • Схеми в реєстрі, включені перевірки сумісності.
  • Ідемпотентність споживачів реалізована і протестована.
  • Налаштовані DLQ/parking lot і алерти на помилки публікації/споживання.
  • Проекції пересоздаются з логу (replay) з прийнятним часом.
  • Обмежений доступ до PII; мінімальні payload'и в ядрі.
  • SLA по лагах/доставці заміряються і видно на дашбордах.
  • Є план міграції версій подій і вікон депрекейту.

FAQ

Чим EDC відрізняється від «просто шини»?
Ядро - це не тільки брокер, але і контракт подій, правила порядку/ідемпотентності, процеси еволюції і спостережуваність.

Чи можна будувати тільки на CDC?
CDC підходить для інтеграцій/міграцій, але доменні події ясніше виражають сенс і стабільніше переживають зміни БД.

Як бути з узгодженістю?
Приймаємо eventual consistency і проектуємо UX/процеси під неї (індикатори оновлення, ретраї, компенсації).

Коли потрібен exactly-once?
Рідко: коли подвоєння строго неприпустимо і неможливо компенсувати. Частіше досить at-least-once + ідемпотентність.

Підсумок

Event-Driven ядро перетворює потік бізнес-фактів в надійний фундамент системи. Чіткі контракти подій, дисципліна доставки і спостережуваність дають масштабованість, стійкість і швидкість еволюції - без крихких синхронних зв'язків і «шторму» регресій при змінах.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.