CDC и Debezium на собеседовании Data Engineer

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.

Зачем CDC

Change Data Capture — поток изменений из OLTP-БД в DWH в реальном времени. Альтернатива — ночные batch-выгрузки полной таблицы. На больших таблицах batch занимает часы, нагружает прод, теряет промежуточные изменения (Customer status: new → active → cancelled за 5 минут — batch увидит только cancelled).

Главная боль без CDC — отчёты опаздывают на сутки, поведение «шёл-шёл и передумал» не виден в DWH. С CDC данные в DWH — почти онлайн, но возникают новые грабли: ordering, дубли, schema changes.

На собесе DE спрашивают: «Что такое CDC?», «Чем log-based отличается от query-based?», «Как работает Debezium?». Это middle+-уровень, junior часто плывёт.

Query-based CDC

Самый простой подход — SELECT по updated_at:

SELECT * FROM orders WHERE updated_at > :last_run

Плюсы:

  • Не требует доступа к replication log БД
  • Работает на любой БД с timestamp-колонкой

Минусы:

  • DELETE незаметен. Удалённая строка просто исчезает из выборки.
  • Hard updates без изменения updated_at теряются.
  • Нагружает БД полным scan по индексу
  • Не ловит промежуточные значения (между запусками строка могла поменяться 5 раз)
  • Late writes: данные с updated_at < last_run пишутся позже — пропустим

Когда применять: dimensions, которые меняются редко, без DELETE; маленькие таблицы; нет доступа к replication log.

Log-based CDC и Debezium

Log-based CDC — читать журнал изменений БД:

  • Postgres: WAL через wal2json или pgoutput (logical replication)
  • MySQL: binlog
  • Oracle: LogMiner / GoldenGate
  • MS SQL: SQL Server CDC / change tracking
  • MongoDB: oplog

Debezium — open-source CDC платформа поверх Kafka Connect. Подключается к БД, читает log, публикует события в Kafka.

[Postgres WAL] → Debezium PG connector → Kafka topic "orders" → consumers (DWH, search, cache)

Формат события Debezium (упрощённо):

{
  "op": "u",
  "before": {"id": 1, "amount": 100, "status": "new"},
  "after":  {"id": 1, "amount": 100, "status": "paid"},
  "source": {"ts_ms": 1730000000, "lsn": "0/16B6378"},
  "ts_ms": 1730000001
}

op: c create, u update, r snapshot read, d delete.

Плюсы log-based:

  • DELETE регистрируется
  • Не нагружает БД (читаем log, не таблицы)
  • Все промежуточные состояния
  • Минимальная задержка (миллисекунды)

Минусы:

  • Сложнее настройка (replication slot, права в БД)
  • Schema changes требуют отдельной обработки
  • Replication slot в Postgres лочит WAL — если consumer отстаёт, диск заполняется

Snapshot и стриминг

При первом запуске Debezium делает initial snapshot — читает таблицу полностью, эмитит события op=r. После этого переключается на чтение log.

T1: snapshot всех 10М строк → эмитит 10М `op=r` событий
T2: подключается к log с момента T0
T3: пишет реальные изменения (`c`/`u`/`d`)

Snapshot-стратегии:

  • initial — снимок один раз при первом запуске (дефолт)
  • never — без снимка, только новые изменения
  • initial_only — снимок и завершить
  • when_needed — снимок только при потере позиции в log

Грабля: во время snapshot БД лочится (на innodb-lock или snapshot-isolation). На больших таблицах — часами. Решения: incremental snapshot (Debezium 1.6+) — снимок без лока, по чанкам.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Доставка в DWH

CDC-события из Kafka → DWH. Два паттерна:

Append-only / event log в DWH:

fact_orders_changelog:
| ts_ms | op | order_id | amount | status |
| 1000  | c  | 1        | 100    | new    |
| 2000  | u  | 1        | 100    | paid   |
| 3000  | d  | 1        | NULL   | NULL   |

Финальное состояние получаем через окно argMax или LAST_VALUE OVER (PARTITION BY order_id ORDER BY ts_ms).

Materialized current state в DWH:

fact_orders:  (текущее состояние)
| order_id | amount | status |

Поддерживается через MERGE/UPSERT по событиям. Дороже на write, дешевле на read.

В ClickHouse — ReplacingMergeTree с версионной колонкой и регулярным OPTIMIZE FINAL. В Iceberg/Delta — MERGE INTO.

Дедупликация: Kafka гарантирует at-least-once, дубли возможны. Дедуплицировать по (source.lsn/source.ts_ms/event_id).

Schema changes

ALTER TABLE в OLTP — отдельная история CDC.

  • Add column: безопасно, новый column в новых событиях
  • Drop column: последующие события без колонки — DWH должен принять как NULL
  • Rename column: разрыв совместимости, обработать вручную
  • Type change: тяжёлый случай, обычно — миграция

Debezium публикует schema change topic с DDL-операциями. DWH-сторона должна слушать и эволюционировать схему.

В Iceberg/Delta schema evolution встроена. В Parquet+Glue — через Glue Catalog.

Частые ошибки

Query-based CDC без soft-delete. DELETE в OLTP не виден. Решение: либо soft-delete (deleted_at), либо log-based.

Не мониторить replication slot lag. Debezium не успевает читать → Postgres держит WAL → диск кончается → авария.

Игнорировать ordering. В Kafka сообщения в одной партиции упорядочены. Если ключ partition = id, события одного id идут в порядке. Если ключ другой — порядок не гарантирован.

Снапшот без incremental на 1ТБ-таблице. Часовой down БД. Использовать incremental snapshot.

Нет idempotency у consumer. Дубли из Kafka попадают в DWH. UPSERT по бизнес-ключу или дедуп по offset.

Не обработать tombstone. Debezium DELETE — событие с op=d, after=null + tombstone (null payload) для compaction. Consumer должен корректно обработать оба.

Без backfill через Debezium для исторических данных. Snapshot захватит текущее состояние, но история изменений до Debezium — потеряна. Если нужна история — параллельно догружать из dump'ов.

Связанные темы

FAQ

Debezium или Kafka Connect JDBC source — что выбрать?

JDBC source — query-based, прост, но без DELETE и снимков. Debezium — log-based, сложнее настроить, но мощнее. Для прод-критичных пайплайнов — Debezium.

Можно ли без Kafka запустить CDC?

Можно: Debezium Server / Debezium Embedded Engine (без Kafka Connect). Но Kafka даёт buffer, replay, fan-out — для прод обычно используют с Kafka.

Что такое exactly-once в Debezium?

Debezium гарантирует at-least-once через Kafka. Exactly-once в DWH — забота consumer-стороны (idempotent UPSERT по primary key).

CDC заменяет ETL?

Не полностью. CDC даёт изменения, ETL/ELT — трансформации. Современный паттерн: CDC → raw layer (bronze) → dbt трансформирует в silver/gold.

Debezium работает с Postgres replicas?

Да, через physical replication, но логическая (WAL) предпочтительнее. С Postgres ≥ 10 — pgoutput / wal2json плагины.

Это официальная информация?

Нет. Статья основана на документации Debezium, Postgres logical replication, Kafka Connect. Конкретные настройки зависят от версий и стека компании.


Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.