Проектирование Ingestion Pipeline
Первый deliverable capstone-проекта — проектирование ingestion pipeline: от OLTP-базы через Kafka до landing zone в object storage. Ключевые решения: какой serialization формат, как настроить Schema Registry, какая стратегия schema evolution.
Требования из обзора проекта:
- 10K events/sec steady, 50K peak (Black Friday)
- Schema меняется ~2 раза в месяц
- Consumer lag SLA: не более 5 минут
- Три типа источников: CDC (PostgreSQL), clickstream, external APIs
Анатомия CDC-события
Прежде чем выбирать формат, разберём что именно мы сериализуем:
Debezium Change Event
Debezium CDC event — JSON-структура с envelope. Содержит before/after state строки, metadata операции, и source info (LSN, timestamp, connector name). Для production обязателен перевод в бинарный формат.Debezium по умолчанию генерирует JSON. Это удобно для debugging, но в production неприемлемо: JSON не имеет schema enforcement, занимает в 3-5 раз больше места, парсинг медленнее. Переход на бинарный формат — первый шаг оптимизации. См. JSON limitations из Модуля 06.
Serialization: Avro vs Protobuf для CDC
Для Kafka-based CDC pipeline два реальных кандидата: Apache Avro и Protocol Buffers. Сравним их в контексте нашего сценария:
Apache Avro
Apache Avro — row-based формат с встроенной schema. Schema идёт вместе с данными (или через Schema Registry). Нативная интеграция с Kafka + Confluent экосистемой.Protocol Buffers
Protocol Buffers — binary формат от Google. Schema определяется в .proto файлах, компилируется в code. Более компактный чем Avro для некоторых типов данных.Рекомендация для capstone-сценария
Решение: Avro
Для нашего capstone-сценария Avro — рациональный выбор. Не потому что 'лучше', а потому что: (1) Debezium + Schema Registry — zero-config path, (2) Spark/Flink consumers читают Avro нативно, (3) schema evolution через Schema Registry покрывает наши ~2 изменения/месяц.Если бы наш pipeline был gRPC-based (микросервисы вместо Kafka), Protobuf был бы более естественным выбором — единый IDL для RPC и сериализации. Контекст определяет решение. См. comparison из Модуля 05.
Schema Registry: конфигурация
Schema Registry — центральный компонент нашего ingestion pipeline. Он обеспечивает контракт между producers (Debezium) и consumers (Spark/Flink):
Debezium (Producer)
Debezium (producer) — регистрирует schema при первом event, обновляет при schema change в PostgreSQL. Каждый event содержит schema ID (4 bytes) вместо полной schema — экономия 90%+ на размере message.Clickstream (Producer)
Clickstream producer — отдельная Avro schema для web-событий. Schema зарегистрирована вручную перед деплоем нового event type. Более стабильная чем CDC — меняется реже.Schema Registry
Confluent Schema Registry — HTTP-сервис, хранит Avro/Protobuf/JSON schemas с версионированием. Subject naming strategy: TopicNameStrategy (topic → schema). Compatibility check на каждый register. Хранит schemas в Kafka internal topic (_schemas).Spark (Consumer)
Spark Structured Streaming — consumer, который читает Avro events из Kafka. Использует Schema Registry для десериализации: по schema ID из message header получает полную schema, десериализует binary → Row.Flink (Consumer)
Flink CDC consumer — альтернативный consumer для real-time processing. Та же Schema Registry интеграция. Может обрабатывать schema changes on-the-fly без restart.Compatibility Mode
Ключевая настройка Schema Registry — compatibility mode. Для нашего CDC сценария:
Подробный разбор compatibility modes — в Модуле 10, Урок 02. Здесь мы применяем эти правила к нашему сценарию, а не повторяем теорию.
Рекомендация: BACKWARD compatibility для всех CDC subjects:
- PostgreSQL
ALTER TABLE ADD COLUMN→ Avro schema добавляет nullable field → BACKWARD compatible - PostgreSQL
ALTER TABLE DROP COLUMN→ Avro schema удаляет field → BACKWARD compatible (новый reader не ожидает поля) - PostgreSQL
ALTER TABLE ALTER COLUMN TYPE→ breaking change → требует новый topic или ручную миграцию
Для clickstream subjects — FULL compatibility: schema меняется редко и контролируется нами.
Schema Design: Avro для CDC
Пример Avro schema для CDC-таблицы orders:
PostgreSQL: orders table
PostgreSQL таблица orders: id (BIGINT), user_id (BIGINT), status (VARCHAR), total (NUMERIC), created_at (TIMESTAMP), updated_at (TIMESTAMP). Debezium маппит SQL types → Avro types.Ключевые решения schema design
Consumer Design: от Kafka до Bronze
Последний блок ingestion — как consumer читает из Kafka и приземляет данные в bronze layer:
Kafka Topic (Avro CDC)
Kafka topic с Avro-encoded CDC events. Партиционирование по PK (id). Гарантия ordering в пределах партиции. Consumer group: spark-bronze-consumer.Spark Consumer
Spark Structured Streaming читает из Kafka, десериализует Avro через Schema Registry, добавляет metadata (ingestion_ts, kafka_offset, kafka_partition). Trigger: micro-batch каждые 30 секунд (balance между latency и throughput).Bronze Layer (S3 + Table Format)
Bronze layer в S3/MinIO: файлы в выбранном формате (file format + table format). Партиционирование по ingestion_date (date from ingestion_timestamp). Append-only: никогда не обновляем bronze. Retention: 3 года.Настройки Consumer
Выбор file и table format для bronze layer — тема следующего урока. Здесь мы фокусируемся на ingestion: как данные попадают из PostgreSQL в Kafka и из Kafka — к порогу bronze layer.
Clickstream Pipeline
CDC — не единственный источник. Clickstream имеет другие характеристики:
Web SDK (JSON events)
Web application отправляет events через SDK: page_view, click, search, add_to_cart, purchase. JSON payload. Объём: ~100K events/sec peak (в 10 раз больше чем CDC).Gateway → Avro conversion
Gateway service: принимает JSON, валидирует, конвертирует в Avro, публикует в Kafka. Avro schema строго определена — gateway отклоняет events не matching schema. Rate limiting: 100K events/sec.Kafka: clickstream-events (24 partitions)
Kafka topic: clickstream-events. Партиционирование по user_id (хэш). Больше партиций чем CDC (24 vs 12) — выше throughput requirement. Retention: 3 дня (clickstream менее ценен для replay чем CDC).Различия в schema strategy
| Параметр | CDC Pipeline | Clickstream Pipeline |
|---|---|---|
| Schema source | PostgreSQL DDL → Debezium auto | Вручную определённая .avsc |
| Compatibility | BACKWARD | FULL |
| Change frequency | ~2 раза/месяц (DDL changes) | ~1 раз/квартал (SDK update) |
| Evolution strategy | Auto-register by Debezium | Manual register before deploy |
| Validation | Schema Registry at write time | Gateway + Schema Registry |
Упражнение: проектирование ingestion
Ваша задача — описать ingestion pipeline для capstone-платформы. Ответьте на вопросы:
Не существует единственного правильного ответа. Вы можете выбрать Protobuf вместо Avro, если обоснование убедительно. Можете выбрать Flink вместо Spark Structured Streaming, если аргументируете trade-offs. Ключ — обоснование, а не конкретный выбор.
Переход к Storage Layer
Ingestion pipeline заканчивается на пороге bronze layer: данные десериализованы, обогащены metadata, готовы к записи. В следующем уроке вы выберете:
- File format для каждого слоя (Parquet vs ORC vs Arrow)
- Table format (Delta Lake vs Iceberg vs Hudi)
- Encoding strategy per column type
- Compression codec per layer
- Partitioning и sort order
Решения ingestion layer влияют на storage: если вы выбрали Avro для Kafka, consumer должен десериализовать Avro → Row и сериализовать Row → Parquet/ORC. Overhead этой conversion — один из факторов при выборе file format.