Сталкивался ли с концепцией Data Contracts (Данные по контракту)?

«Сталкивался ли с концепцией Data Contracts (Данные по контракту)?» — вопрос из категории Качество данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, внедрял Data Contracts в проекте по построению централизованного Data Lake. Data Contract — это формальное соглашение между производителем (например, сервис, генерирующий события) и потребителями данных (аналитики, ML-инженеры) о структуре, семантике, качестве и SLA данных.

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

  • Схема данных: Точная структура (например, Avro-схема для Kafka-топика или DDL для таблицы).
  • Семантика полей: Бизнес-описание каждого поля, допустимые значения, единицы измерения.
  • Метрики качества: Ожидаемая полнота, свежесть (latency), уникальность ключей.
  • SLA и ownership: Владелец набора данных, график обновления, срок хранения, процедура на случай breaking changes.

Техническая реализация, которую мы применяли:

  1. Хранение контрактов: Схемы хранились в Git-репозитории как .avsc или .sql файлы. Метаданные (описание, владелец, SLA) — в отдельной служебной БД (PostgreSQL).
  2. Валидация на лету: Для Kafka использовали Schema Registry (Confluent или Apicurio), который проверял соответствие отправляемых событий зарегистрированной Avro-схеме.
  3. Мониторинг соблюдения: Написали даг в Airflow, который ежедневно запускал DQ-чеки (с помощью Great Expectations) и сравнивал метрики (например, процент null в ключевом поле) с порогами, указанными в контракте. При нарушении алертил владельца.

Пример фрагмента Data Contract для топика user_activity в виде YAML:

schema_version: "1.0"
owner_team: "analytics-team"
slas:
  freshness: "5 minutes"  # Максимальная задержка данных
  availability: "99.9%"

schema:
  type: "AVRO"
  fields:
    - name: "user_id"
      type: "string"
      description: "UUID пользователя"
      quality_rules:
        - "completeness > 99.5%"
        - "regex_match: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
    - name: "event_timestamp"
      type: "long"
      description: "Unix timestamp события в миллисекундах"
      quality_rules:
        - "is_within_last_7_days"

Это позволило резко сократить количество инцидентов, когда падали дашборды или ETL-пайплайны из-за неожиданных изменений в данных.