Схемы данных и их эволюция
1) Зачем это iGaming-платформе
Надежность: изменения в данных не ломают отчеты, API и модели.
Скорость фич: безопасно добавляем поля (KYC/RG/PSP), не останавливая стримы.
Регуляторика: прослеживаемость и воспроизводимость (audit/lineage, DSAR, Legal Hold).
Стоимость: минимизируем «переливы» и даунтайм бэкфиллов.
2) Типы схем и где они живут
События (стримы): `payments.deposit_accepted`, `game.round_finished`.
OLTP/DDL: нормализованные таблицы (KYC, аккаунты, лимиты).
DWH/витрины (Gold): денормализованные агрегаты под BI/ML.
Feature Store: онлайновые/офлайновые фич-сеты с гарантиями согласованности.
Контракты внешних партнеров: PSP, провайдеры игр, маркетинговые источники.
Нотации: Avro/Protobuf (стримы), JSON Schema (интеграции), SQL DDL (DWH), Parquet schema (lake).
3) Совместимость (ядро эволюции)
Backward-compatible: новые продьюсеры → старые консьюмеры (добавили поле c default/nullable).
Forward-compatible: старые продьюсеры → новые консьюмеры (новый читатель игнорирует лишнее).
Full-compatible: и то, и другое (желательная цель для событий).
Breaking-changes: переименование/удаление поля, смена типа/семантики, изменение ключа/partitioning.
Правило 1: события эволюируем через добавление, не через изменение.
Правило 2: удалять — только в MAJOR версии схемы после периода депрекейта.
4) Семантические версии и политики
`MAJOR.MINOR.PATCH` для каждой схемы/витрины/фич-сета.
MAJOR — несовместимо (новый topic/таблица/фич-сет, dual-run).
MINOR — совместимо (новые nullable/default поля, новые enum-значения).
PATCH — правки описаний/лимитов/комментариев.
Жизненный цикл поля: `experimental → active → deprecated → removed` (с датами и владельцем).
5) Реестр схем и контракты данных
Schema Registry: хранит версии, совместимость, эволюцию и владельцев.
Data Contract: фиксирует схему + SLO качества + приватность (см. раздел «Валидация данных»).
json
{
"type":"record","name":"deposit_accepted","namespace":"payments",
"fields":[
{"name":"event_id","type":"string"},
{"name":"occurred_at","type":{"type":"long","logicalType":"timestamp-micros"}},
{"name":"user_id","type":"string"},
{"name":"brand","type":"string"},
{"name":"country","type":"string"},
{"name":"psp","type":"string"},
{"name":"method","type":"string"},
{"name":"amount","type":{"type":"bytes","logicalType":"decimal","precision":18,"scale":2}},
{"name":"currency","type":{"type":"enum","name":"Currency","symbols":["EUR","USD","TRY","BRL"]}},
{"name":"risk_score","type":["null","int"],"default":null}, // MINOR+
{"name":"kyc_level","type":["null",{"type":"enum","name":"Kyc","symbols":["L0","L1","L2","L3"]}],"default":null}
],
"compatibility":"FULL","owner":"team-payments"
}
6) Паттерны миграций
6.1 События (стримы)
Additive-only: добавляем поля с default/nullable; старые консьюмеры не ломаются.
Enum-расширения: новые символы считаются MINOR, консьюмеры обязаны иметь ветку `else/unknown`.
MAJOR-миграция: новый topic `payments.deposit_accepted.v2`, dual-write, shadow-reads, потом переключение консьюмеров.
6.2 DWH/витрины
Blue-Green таблицы: `gold.revenue_v2` рядом с `v1`; материализуем, сверяем, переключаем BI.
Backfill: реплей по снапшотам + idempotent merge (по ключам/версиям).
SCD: тип 2 для медленно меняющихся атрибутов (лимиты, KYC, VIP-статусы).
6.3 Feature Store
Dual-serve: старый фич-сет обслуживается параллельно новому; модель обслуживается через роутер.
Point-in-time согласованность: эволюция не должна ломать PITA-джойны (timestamp/гранулярность неизменны при MINOR).
7) Таксономия изменений (чек-лист)
Безопасные (MINOR):- добавление `nullable/default` поля;
- расширение enum (с `unknown`-веткой у потребителя);
- добавление неключевого индекса/комментария/описаний.
- смена масштаба/единиц (например, amount в центах → в основной валюте) — только в MAJOR;
- перенос справочника/референса — через слой представления.
- переименование/удаление поля;
- изменение типа/формата/ключа/partition;
- смена семантики (например, `bonus_amount` из «начислено» → «списано»).
8) Линтеры схем и тесты совместимости
Schema-lint: стиль имен (`snake_case`), обязательные метки (`owner`, `doc`, `pii`), формат дат/валют.
Compat-tests: проверяем новую версию против реестра (backward/forward/full).
Consumer-contract-tests: каждый сервис поставляет «пример полезной нагрузки» и ожидания; прогоняем на CI при смене схемы.
Golden-datasets: набор реальных и «злых» примеров (новые enum, пустые/поздние поля, рубежные значения сумм).
9) Справочники, enum и локализация
Reference-data (страны/валюты/PSP/провайдеры): отдельные версии и SLA обновлений; не вшивать в код событий.
Locale/часовые пояса: хранить UTC в событиях + явную локаль для презентации.
Правила юрисдикций: возрастные флаги, ограничения промо — в виде справочников с датами действия.
10) Мультибренд/мультиюрисдикции и PII
Тенант-изоляция: `brand`, `country`, `license` — обязательные поля с enum; роутинг по ним.
PII-политика на уровне схемы: помечаем поля `pii=true`, применяем маски/токенизацию; в событиях — только токены.
DSAR: наличие `source_id/trace_id` для удаления/поиска; Legal Hold на MAJOR-миграциях.
11) Версионирование DDL и Lake
DDL-миграции: декларативные миграции (Liquibase/Flyway/dbt), хранение в VCS, ревью владельцем домена.
Форматы в Lake: Avro/Parquet — фиксируем эволюцию полей; при MAJOR — новая таблица/путь `.../v2/`.
Partitioning: изменение партиций (например, `date`→`date,brand`) — только через MAJOR и двойную запись.
12) Примеры iGaming
12.1 PSP расширил методы
Добавлен `method="MEFETE"` в enum.
MINOR релиз схемы `deposit_accepted v1.8.0`; консьюмеры, не знающие MEFETE, отправляют в `unknown_method` ветку.
12.2 Провайдер игр добавил поля
В `game.round_finished` добавлено `jackpot_id` (nullable).
Витрина `gold.game_rounds_v3` получает MINOR; старые отчеты работают, новые считают джекпоты.
12.3 RG-атрибуты
Переход от булевого `self_excluded` к статусовому `rg_state ∈ {none, limit, cooldown, self_excluded}` — MAJOR, новый topic + dual-write + миграция витрин и моделей.
13) Процесс эволюции (от идеи до переключения)
1. Proposal (ADR): зачем меняем, тип совместимости, оценка риска и затронутых потребителей.
2. Дизайн и контракт: схема в реестр, semver, политика совместимости.
3. Тесты: linters, compat, consumer-contracts, реплей на golden-сетах.
4. Развертывание: dual-write / blue-green / shadow-reads; алерты.
5. Сверка: бизнес-балансы/инварианты (см. «Валидация данных»).
6. Switch: переключаем консьюмеров/BI/фичи.
7. Deprecate: freeze старой схемы, grace-period, удаление и архив.
14) Метрики и SLO эволюции
Success-rate миграций, время dual-run, доля событий нового формата, объем backfill, lag/freshness.
Инциденты совместимости (P1/P2), качество витрин после переключения.
Cost: $/TB перелива, $/час dual-write, загрузка кластера.
Compliance: 0 PII-утечек, SLA DSAR/Legal Hold соблюдены.
15) Инструменты и артефакты
15.1 Политика совместимости (реестр)
yaml schema: payments. deposit_accepted compatibility: FULL default_nulls: true enums:
currency: {allow_new_symbols: true, require_consumer_unknown_branch: true}
pii: false owners: ["team-payments"]
reviewers: ["data-governance","security-dpo"]
15.2 Паспорт миграции (шаблон)
yaml change_id: MIG-2025-041 scope: game. round_finished -> v3 type: MAJOR plan:
dual_write: true shadow_reads: consumers: ["gold-rounds","rg-models"]
backfill: {from: "2025-01-01", mode: "idempotent-merge"}
validation:
invariants: ["sum_bets = sum_wins + margin + bonuses"]
freshness_delta_p95_max: "PT5M"
switch_criteria:
error_rate_max: 0. 1%
kpi_diff_pp_max: 0. 5 deprecate_after: "2025-12-31"
15.3 Линтер имен и типов (правила)
`snake_case`, UTC timestamps, DECIMAL(18,2) для сумм, `country` по ISO-3166-1 alpha-2, `currency` по ISO-4217.
Никаких `free_text` для enum-полей; справочники — внешние.
16) Дорожная карта внедрения
0–30 дней (MVP)
1. Включить Schema Registry + policy совместимости для ключевых событий (payments, game_rounds, user).
2. Линтеры/compat-тесты в CI; каталог владельцев и SLA отзывов.
3. Шаблоны ADR и паспорт миграций; чек-лист MAJOR.
30–90 дней
1. Blue-Green для Gold-витрин; dual-write для критичных тем.
2. Consumer-contract-tests для основных сервисов; golden-datasets.
3. Автоматические diff-сверки и алерты при переключениях; отчеты стоимости.
3–6 месяцев
1. Единый процесс deprecate/remove с grace-period; архивирование и Legal Hold.
2. Гео/тенант-специфичные схемы и ключи шифрования; DP-варианты для чувствительных рынков.
3. Каталог семантики полей (data dictionary) и живые диаграммы lineage.
17) RACI
Data Governance (A/R): стандарты, реестр, ревью миграций, де-публикация.
Domain Owners (R): смысл полей, справочники, бизнес-инварианты.
Data Platform (R): инструменты реестра, compat-тесты, dual-run/бэкфиллы.
Security/DPO (A/R): PII-политики, geo/tenant, DSAR/Legal Hold.
SRE/Observability (C): алерты, SLO эволюций, capacity.
Product/Finance (C): валидация KPI, окна переключения.
18) Анти-паттерны
«Правим поле на лету» без версий и dual-run.
Переименование вместо добавления нового поля → массовые поломки.
Жесткие enum без ветки `unknown` → падения при новых значениях.
Единый справочник «в коде» для всех юрисдикций.
Бэкфилл без idempotent-merge и чек-балансов.
Логи с PII и без trace_id для поиска/DSAR.
19) Связанные разделы
Валидация данных, Происхождение и путь данных, DataOps-практики, API аналитики и метрик, Аудит и версионность, Безопасность данных и шифрование, Контроль доступа, MLOps: эксплуатация моделей.
Итог
Эволюция схем — это процесс, а не разовая миграция: реестр, версии и совместимость; dual-run и blue-green вместо «переключателей в полночь»; тесты совместимости и бизнес-инварианты вместо удачи. Так данные остаются стабильными, модели — предсказуемыми, отчеты — корректными, а регуляторы — спокойными.