Глоссарий — Debezium CDC Mastery
Справочник ключевых терминов курса Debezium CDC Mastery. Определения, примеры и ссылки на уроки.
5 категорий · 27 терминов
Навигация по категориям
Совет: Используйте Cmd+K (Ctrl+K) для быстрого поиска по терминам
PostgreSQL
WAL
Write-Ahead LogЖурнал упреждающей записи — механизм ACID-гарантий в PostgreSQL. Все изменения сначала записываются в WAL, затем применяются к данным. Debezium читает WAL через логическую репликацию для захвата изменений без нагрузки на production базу.
-- Просмотр текущей позиции WAL
SELECT pg_current_wal_lsn();
-- Результат: 0/16B9F08
-- Размер несинхронизированного WAL
SELECT pg_wal_lsn_diff(
pg_current_wal_lsn(),
confirmed_flush_lsn
) FROM pg_replication_slots
WHERE slot_name = 'debezium';LSN
Log Sequence NumberУникальный идентификатор позиции в WAL. Используется для отслеживания прогресса репликации и определения лага. Формат: 16/3E8A0F00 где первая часть — номер файла WAL, вторая — смещение внутри файла.
-- Текущий LSN
SELECT pg_current_wal_lsn();
-- Результат: 0/16B9F08
-- LSN в числовом формате (для расчёта лага)
SELECT pg_wal_lsn_diff('0/16B9F08', '0/16B9E00');
-- Результат: 264 байтаReplication Slot
Слот репликацииМеханизм PostgreSQL для отслеживания прогресса логической репликации. Слот гарантирует, что WAL-сегменты не будут удалены до тех пор, пока Debezium их не прочитает. КРИТИЧНО: неиспользуемые слоты приводят к переполнению диска.
-- Просмотр активных слотов
SELECT slot_name, active, restart_lsn,
confirmed_flush_lsn
FROM pg_replication_slots;
-- Создание слота для Debezium
SELECT pg_create_logical_replication_slot(
'debezium',
'pgoutput'
);
-- Удаление слота (потеря позиции!)
SELECT pg_drop_replication_slot('debezium');Logical Decoding
Логическое декодированиеМеханизм PostgreSQL для извлечения изменений из WAL в читаемом формате. Logical decoding преобразует низкоуровневые WAL-записи в структурированные события (INSERT, UPDATE, DELETE) с именами таблиц и значениями полей. Debezium использует logical decoding через плагин pgoutput.
-- Проверка доступных плагинов
SELECT * FROM pg_available_extensions
WHERE name = 'pgoutput';
-- Создание слота с плагином декодирования
SELECT pg_create_logical_replication_slot(
'test_slot',
'pgoutput'
);
-- Чтение изменений (для тестирования)
SELECT * FROM pg_logical_slot_peek_changes(
'test_slot',
NULL,
NULL
);Publication
ПубликацияОбъект PostgreSQL, который определяет набор таблиц для логической репликации. Publication указывает, какие таблицы и операции (INSERT/UPDATE/DELETE) должны реплицироваться. Debezium автоматически создаёт publication для указанных таблиц.
-- Создание publication для всех таблиц
CREATE PUBLICATION dbz_publication
FOR ALL TABLES;
-- Publication для конкретных таблиц
CREATE PUBLICATION dbz_publication
FOR TABLE customers, orders;
-- Только INSERT и UPDATE (без DELETE)
CREATE PUBLICATION dbz_publication
FOR TABLE customers
WITH (publish = 'insert, update');
-- Просмотр publications
SELECT * FROM pg_publication;pgoutput
Плагин pgoutputВстроенный плагин PostgreSQL для logical decoding (с версии 10+). pgoutput — нативный плагин, который не требует отдельной установки, в отличие от wal2json или decoderbufs. Debezium по умолчанию использует pgoutput для максимальной совместимости.
-- PostgreSQL config для pgoutput
wal_level = logical
max_replication_slots = 4
max_wal_senders = 4
-- Connector config
{
"plugin.name": "pgoutput",
"publication.name": "dbz_publication"
}
-- Проверка использования pgoutput
SELECT slot_name, plugin
FROM pg_replication_slots;
-- Результат: debezium | pgoutputMySQL
Binlog
Binary LogБинарный лог MySQL, который записывает все изменения данных для репликации и восстановления. Debezium читает binlog для захвата CDC событий. Формат может быть STATEMENT, ROW или MIXED (только ROW поддерживается Debezium).
-- Проверка включения binlog
SHOW VARIABLES LIKE 'log_bin';
-- Текущая позиция binlog
SHOW MASTER STATUS;
-- Список binlog файлов
SHOW BINARY LOGS;
-- Установка retention периода
SET GLOBAL expire_logs_days = 7;
SET GLOBAL binlog_expire_logs_seconds = 604800;GTID
Global Transaction IdentifierГлобальный идентификатор транзакции в MySQL. GTID упрощает репликацию и восстановление, делая позицию в binlog независимой от конкретного файла. Формат: server_uuid:transaction_id (например, 3E11FA47-71CA-11E1-9E33-C80AA9429562:23).
-- Проверка включения GTID
SHOW VARIABLES LIKE 'gtid_mode';
-- Текущий executed GTID set
SHOW MASTER STATUS;
-- GTID purged (удаленные binlog)
SHOW GLOBAL VARIABLES LIKE 'gtid_purged';server_id
Идентификатор сервера MySQLУникальный идентификатор MySQL сервера в топологии репликации. Каждый сервер (master, slave, Debezium) должен иметь уникальный server_id. Debezium использует server_id для идентификации себя как replica и для чтения binlog.
-- Просмотр текущего server_id
SHOW VARIABLES LIKE 'server_id';
-- my.cnf конфигурация
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW
-- Connector config
{
"database.server.id": "184054",
"database.hostname": "mysql",
"database.port": "3306"
}binlog_format
Формат binlogФормат записи изменений в binlog. Может быть STATEMENT (SQL-запросы), ROW (изменённые строки) или MIXED. Debezium поддерживает ТОЛЬКО binlog_format=ROW, так как только ROW-формат содержит полные значения полей до и после изменения.
-- Проверка формата binlog
SHOW VARIABLES LIKE 'binlog_format';
-- my.cnf конфигурация (обязательно для Debezium)
[mysqld]
binlog_format = ROW
binlog_row_image = FULL
-- Изменение в runtime (требует SUPER привилегии)
SET GLOBAL binlog_format = 'ROW';binlog_row_image
Объём данных в ROW событииПараметр MySQL, определяющий, какие колонки записываются в binlog при UPDATE. Может быть FULL (все колонки), MINIMAL (только PK и изменённые), NOBLOB (без BLOB/TEXT). Debezium требует FULL для получения complete before/after state.
-- Проверка binlog_row_image
SHOW VARIABLES LIKE 'binlog_row_image';
-- my.cnf конфигурация
[mysqld]
binlog_row_image = FULL
-- MINIMAL (экономит место, но Debezium не увидит неизменённые поля)
binlog_row_image = MINIMAL
-- Пример события с FULL
UPDATE users SET email = '[email protected]' WHERE id = 1;
-- Binlog содержит: id, name, email (до и после)Kafka
Topic
Топик KafkaКатегория или поток сообщений в Kafka. Debezium создаёт отдельный топик для каждой таблицы (по умолчанию формат: server_name.schema_name.table_name). Топики делятся на партиции для параллельной обработки.
# Список топиков Debezium
kafka-topics --list --bootstrap-server localhost:9092 \
| grep dbserver1
# Информация о топике
kafka-topics --describe \
--topic dbserver1.inventory.customers \
--bootstrap-server localhost:9092
# Чтение сообщений из топика
kafka-console-consumer \
--bootstrap-server localhost:9092 \
--topic dbserver1.inventory.customers \
--from-beginningOffset
Смещение KafkaУникальный последовательный идентификатор сообщения внутри партиции. Consumer отслеживает offset для управления позицией чтения. Debezium хранит свой offset отдельно для отслеживания прогресса репликации из базы данных.
# Просмотр текущих offset consumer group
kafka-consumer-groups --describe \
--group connect-cluster \
--bootstrap-server localhost:9092
# Сброс offset для повторного чтения
kafka-consumer-groups --reset-offsets \
--group connect-cluster \
--topic dbserver1.inventory.customers \
--to-earliest --executePartition
Партиция KafkaФизическое разделение топика для параллельной обработки и масштабирования. Каждая партиция — упорядоченный лог сообщений. Debezium по умолчанию использует primary key таблицы как ключ партиционирования для сохранения порядка событий одной записи.
# Создание топика с 3 партициями
kafka-topics --create \
--topic dbserver1.inventory.orders \
--partitions 3 \
--replication-factor 2 \
--bootstrap-server localhost:9092
# Просмотр партиций топика
kafka-topics --describe \
--topic dbserver1.inventory.orders \
--bootstrap-server localhost:9092
# Connector config - партиционирование по user_id
{
"transforms": "partitionByUser",
"transforms.partitionByUser.type":
"org.apache.kafka.connect.transforms.ValueToKey",
"transforms.partitionByUser.fields": "user_id"
}Consumer Group
Группа потребителейГруппа Kafka consumers, которые совместно читают сообщения из топика. Каждая партиция читается только одним consumer в группе, что обеспечивает параллельную обработку без дублирования. Kafka Connect создаёт consumer group для каждого коннектора.
# Список consumer groups
kafka-consumer-groups --list \
--bootstrap-server localhost:9092
# Детали группы (offset, lag)
kafka-consumer-groups --describe \
--group connect-debezium-postgres \
--bootstrap-server localhost:9092
# Результат:
# GROUP TOPIC PARTITION OFFSET LAG
# connect-... customers 0 1523 0
# connect-... customers 1 1498 0
# connect-... orders 0 5832 12Debezium
Snapshot
Снимок данныхНачальная полная копия данных из таблицы перед началом потоковой репликации. Debezium делает consistent snapshot без блокировки записей (через MVCC в PostgreSQL или с использованием LOCK TABLES в MySQL).
// Connector config - snapshot mode
{
"snapshot.mode": "initial",
// Полный snapshot при первом запуске
"snapshot.mode": "never",
// Пропустить snapshot, только streaming
"snapshot.mode": "schema_only",
// Только структура таблиц, данные не копируются
"snapshot.mode": "when_needed"
// Snapshot если offset не найден
}Streaming
Потоковая репликацияРежим непрерывного чтения изменений из WAL (PostgreSQL) или binlog (MySQL). После завершения snapshot Debezium переключается в streaming mode и читает только новые изменения в реальном времени с минимальной задержкой.
// Connector status - streaming phase
{
"name": "inventory-connector",
"connector": {
"state": "RUNNING",
"worker_id": "kafka-connect:8083"
},
"tasks": [{
"id": 0,
"state": "RUNNING",
"worker_id": "kafka-connect:8083"
}],
"type": "source"
}Connector
Коннектор DebeziumKafka Connect source connector, который интегрируется с конкретной базой данных (PostgreSQL, MySQL, MongoDB и др.). Коннектор читает изменения через нативные механизмы репликации и публикует события в Kafka.
# Создание коннектора через REST API
curl -X POST http://localhost:8083/connectors \
-H "Content-Type: application/json" \
-d @postgres-connector.json
# Проверка статуса
curl http://localhost:8083/connectors/inventory-connector/status
# Удаление коннектора
curl -X DELETE \
http://localhost:8083/connectors/inventory-connectorSMT
Single Message TransformЛегковесные преобразования Kafka Connect, которые применяются к каждому событию перед записью в Kafka. SMT позволяют фильтровать поля, переименовывать топики, маршрутизировать события без написания отдельного приложения.
// Connector config - фильтрация полей
{
"transforms": "unwrap,addPrefix",
// Debezium Unwrap - извлечь только 'after'
"transforms.unwrap.type":
"io.debezium.transforms.ExtractNewRecordState",
"transforms.unwrap.drop.tombstones": false,
// Добавить префикс к топику
"transforms.addPrefix.type":
"org.apache.kafka.connect.transforms.RegexRouter",
"transforms.addPrefix.regex": "(.*)",
"transforms.addPrefix.replacement": "cdc.$1"
}Outbox Pattern
Паттерн OutboxМикросервисный паттерн для надёжной публикации событий. При изменении entity приложение также вставляет событие в outbox таблицу в той же транзакции. Debezium читает outbox таблицу и публикует события в Kafka, гарантируя атомарность обновления и публикации.
-- Outbox таблица
CREATE TABLE outbox (
id UUID PRIMARY KEY,
aggregatetype VARCHAR(255) NOT NULL,
aggregateid VARCHAR(255) NOT NULL,
type VARCHAR(255) NOT NULL,
payload JSONB NOT NULL
);
-- Бизнес-логика (атомарная транзакция)
BEGIN;
UPDATE orders SET status = 'PAID' WHERE id = 123;
INSERT INTO outbox (id, aggregatetype, aggregateid, type, payload)
VALUES (gen_random_uuid(), 'Order', '123', 'OrderPaid',
'{"orderId": 123, "amount": 99.99}'::jsonb);
COMMIT;
// Debezium Outbox SMT
{
"transforms": "outbox",
"transforms.outbox.type":
"io.debezium.transforms.outbox.EventRouter"
}Heartbeat
События heartbeatПериодические события, которые Debezium отправляет в Kafka даже при отсутствии изменений в базе данных. Heartbeat предотвращают удаление binlog/WAL на неактивных таблицах и позволяют отслеживать, что коннектор жив.
// Connector config - heartbeat каждые 5 минут
{
"heartbeat.interval.ms": 300000,
"heartbeat.topics.prefix": "__debezium-heartbeat",
// Heartbeat событие
{
"ts_ms": 1686500577691,
"source": {
"connector": "postgresql",
"name": "dbserver1",
"lsn": 33023704
}
}
}
// Проверка heartbeat топика
kafka-console-consumer \
--topic __debezium-heartbeat.dbserver1 \
--bootstrap-server localhost:9092Tombstone
Tombstone событиеСобытие Kafka с null значением, которое используется для удаления ключа при log compaction. Debezium отправляет tombstone после DELETE события, чтобы при compaction топика запись была полностью удалена.
// DELETE события от Debezium
// 1. DELETE событие (op='d')
{
"before": {"id": 123, "name": "John"},
"after": null,
"op": "d"
}
// 2. Tombstone (следует сразу после)
{
"key": {"id": 123},
"value": null // <- tombstone
}
// Connector config - управление tombstones
{
"transforms": "unwrap",
"transforms.unwrap.type":
"io.debezium.transforms.ExtractNewRecordState",
"transforms.unwrap.drop.tombstones": false
}General CDC
CDC
Change Data CaptureПаттерн захвата изменений данных в реальном времени. Вместо опроса (polling) базы данных, CDC читает журналы транзакций (WAL, binlog) для получения событий INSERT, UPDATE, DELETE с минимальной задержкой и нагрузкой.
// CDC Event Structure (Debezium JSON)
{
"before": null, // Состояние до изменения
"after": { // Новое состояние
"id": 1001,
"name": "John Doe",
"email": "[email protected]"
},
"source": {
"version": "2.1.0.Final",
"connector": "postgresql",
"name": "dbserver1",
"ts_ms": 1486500577691,
"db": "inventory",
"schema": "public",
"table": "customers",
"lsn": 33023704
},
"op": "c", // c=create, u=update, d=delete, r=read
"ts_ms": 1486500584591
}Schema Registry
Реестр схемЦентрализованный сервис для хранения и версионирования схем Avro/Protobuf/JSON Schema. При использовании с Debezium позволяет эффективно сериализовать события и обеспечивает совместимость при эволюции схем таблиц.
# Просмотр зарегистрированных схем
curl http://localhost:8081/subjects
# Получение схемы для топика
curl http://localhost:8081/subjects/\
dbserver1.inventory.customers-value/versions/latest
# Connector config с Schema Registry
{
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":
"http://schema-registry:8081"
}Idempotency
ИдемпотентностьСвойство операции, при котором повторное применение даёт тот же результат, что и однократное. В CDC критично для обработки дубликатов событий (при retry, rebalance). Consumer должен корректно обрабатывать повторную доставку того же события.
// НЕ идемпотентная операция
UPDATE accounts SET balance = balance + 100
WHERE id = 123;
// Повторное применение = двойное начисление!
// Идемпотентная операция (event sourcing)
INSERT INTO account_events (account_id, type, amount, event_id)
VALUES (123, 'CREDIT', 100, 'evt-456')
ON CONFLICT (event_id) DO NOTHING;
// Повторное применение = игнорируется
// Debezium + Kafka idempotent producer
{
"producer.enable.idempotence": true,
"producer.max.in.flight.requests.per.connection": 5
}Exactly-Once
Ровно один разГарантия доставки сообщения, при которой каждое событие обрабатывается ровно один раз без потерь и дубликатов. В Kafka достигается через idempotent producer и transactional API. Debezium + Kafka обеспечивают at-least-once, exactly-once требует idempotent consumer.
// Kafka Streams - exactly-once
Properties props = new Properties();
props.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG,
StreamsConfig.EXACTLY_ONCE_V2);
// Debezium config - основа для exactly-once
{
// Kafka producer идемпотентность
"producer.enable.idempotence": true,
// Consumer должен сам обеспечить идемпотентность
// через deduplication или event_id tracking
}
// Consumer pattern - deduplication
SET processed_events = new Set();
for (event in stream) {
if (!processed_events.has(event.id)) {
process(event);
processed_events.add(event.id);
}
}Event Sourcing
Событийное хранениеАрхитектурный паттерн, где состояние приложения хранится как последовательность событий, а не как текущий snapshot. CDC отлично сочетается с Event Sourcing — изменения базы данных становятся событиями в event log (Kafka), из которых можно восстановить любое состояние системы.
// Event Store структура
CREATE TABLE event_store (
event_id UUID PRIMARY KEY,
aggregate_id VARCHAR(255),
aggregate_type VARCHAR(255),
event_type VARCHAR(255),
event_data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
// CDC события как Event Source
{
"event_id": "evt-123",
"aggregate_id": "order-456",
"aggregate_type": "Order",
"event_type": "OrderPlaced",
"event_data": {
"orderId": 456,
"customerId": 789,
"amount": 99.99
}
}
// Восстановление состояния
SELECT * FROM event_store
WHERE aggregate_id = 'order-456'
ORDER BY created_at;Не нашли термин? Используйте Cmd+K для поиска по всему курсу или обратитесь к соответствующим урокам модулей для более детальной информации. Глоссарий регулярно дополняется новыми терминами.