トランザクションDBの更新をほぼリアルタイムでイベント化し、Kafka に流し込む王道のやり方が Debezium を使った CDC です。アプリの改修を最小化しつつ、低遅延・高整合でデータ連携できます。
本稿は実務でつまずきやすい論点を、Kafka の公式挙動に沿って整理します。あわせて CCDAK で問われやすい観点(Connect、シリアライザ、パーティショニング、配信保証)も明確にします。
Debezium はデータベースの変更ログ(例: MySQL の binlog、PostgreSQL の WAL)を購読し、Kafka Connect の Source コネクタとして変更イベントを Kafka トピックに出力します。アプリ側にトリガや改修を入れず、DB エンジンが保証する順序と一貫性を最大限活用できるのが強みです。
イベントは通常、before/after のレコード、操作種別(c: create, u: update, d: delete, r: snapshot)、タイムスタンプ、ソースメタデータを含むエンベロープ形式でエンコードされます。キーには主キー(もしくは論理キー)を使い、メッセージの整合性と Kafka のパーティション内順序を担保します。
| 方式 | 典型遅延 | 重複/欠損耐性 | スキーマ変化対応 |
|---|---|---|---|
| ログベースCDC(Debezium) | 数百ms〜数秒 | 欠損しづらい。再処理で重複の可能性あり | 列追加等に強い(履歴管理とスキーマ進化を前提) |
| ポーリング(差分クエリ) | 数十秒〜分 | 欠損リスク(更新タイミング競合) | クエリとアプリ側対応が必要 |
| DBトリガ/キュー | アプリ依存 | 実装次第。過負荷や障害時の耐性に注意 | 変更に脆い(トリガ更新が必要) |
RDB→Debezium→Kafka のデータフロー
Debezium は Kafka Connect の Source コネクタとして稼働します。Connect ワーカー(分散/スタンドアロン)にコネクタ設定を POST し、タスクが DB のログを読み取り Kafka に出力します。シリアライザは Confluent の Schema Registry を併用する Avro/Protobuf/JSON Schema、もしくはプレーン JSON(スキーマなし)から選びます。CCDAK ではキー/バリューのコンバータ設定とスキーマ進化の扱いがよく問われます。
PostgreSQL では論理デコード(pgoutput など)が必要です。publication と replication 権限、スロット管理、WAL 設定(十分な保持)が前提です。トピック名は通常 serverName.schema.table の形式になり、トランザクションメタデータ用の内部トピックも生成されます。
POST /connectors への Debezium PostgreSQL コネクタ設定例
{
"name": "inventory-postgres-cdc",
"config": {
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"tasks.max": "1",
"database.hostname": "postgres",
"database.port": "5432",
"database.user": "replicator",
"database.password": "<redacted>",
"database.dbname": "inventory",
"plugin.name": "pgoutput",
"slot.name": "debezium_slot",
"publication.autocreate.mode": "filtered",
"tombstones.on.delete": "true",
"topic.prefix": "dbserver1",
"snapshot.mode": "initial",
"schema.include.list": "public",
"table.include.list": "public.customers,public.orders",
"max.batch.size": "2048",
"max.queue.size": "8192",
"heartbeat.interval.ms": "10000",
"key.converter": "io.confluent.connect.avro.AvroConverter",
"key.converter.schema.registry.url": "http://schema-registry:8081",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url": "http://schema-registry:8081",
"schema.history.internal.kafka.bootstrap.servers": "kafka:9092",
"schema.history.internal.kafka.topic": "schema-changes.inventory",
"topic.creation.default.replication.factor": "3",
"topic.creation.default.partitions": "6",
"topic.creation.default.cleanup.policy": "compact,delete"
}
}Debezium のメッセージは before/after、op、source、ts_ms、transaction などを含むエンベロープ構造です。アップサートを行う下流(例: ksqlDB のテーブル、JDBC Sink での upsert、DWH の MERGE)に繋ぐ場合、Kafka トピックにログコンパクションを設定し、キーに主キー相当を入れるのが基本です。delete は tombstone メッセージで表現され、コンパクションにより最終状態が保たれます。
スキーマ進化(列追加・NULL 可変化など)は Schema Registry の互換性設定で制御します。後方互換を維持する変更を優先し、互換性違反のデプロイをブロックできるようにします。CCDAK では互換性モード(BACKWARD/FORWARD/FULL)と、レコードキー/バリューで別スキーマが管理される点が頻出です。
Kafka Connect はソースの読み取り位置を内部オフセットトピックに保存します。Debezium はこれを用いて binlog/WAL の位置を管理し、再起動後に同位置から再開します。クラスタ再平衡や障害時には少量の重複が発生しうるため、下流は冪等またはアップサートで受ける設計にします。
スナップショットは初回にテーブル全件を読み取り、その後にログ追随に移行します。大規模テーブルではスナップショットを段階的に行う incremental snapshot 機能の検討、業務時間外の実行、I/O 制御が有効です。スナップショットとログ適用の整合は Debezium がトランザクション境界を考慮して処理します。
監視は三層で行います。DB(WAL/binlog 進行と保持)、Connect/Debezium(タスク状態、キュー長、エラー率、ソース位置)、Kafka(パブリッシュレイテンシ、プロデューサリトライ、ブローカー側のスループットとレプリケーション)。Connect と Debezium は JMX メトリクスを公開するため、アラート閾値を明確化します。
パフォーマンスはバッチとキューのサイズ、ポーリング間隔、トピックのパーティション数、レプリケーション係数でバランスします。過剰なパーティションは順序保証とキー偏りを悪化させるため、主キーの一意性とスループットを基に適正値を見積もります。
CCDAK では Kafka Connect の基本、シリアライザと Schema Registry、パーティショニング、ログコンパクション、配信保証(少なくとも一度、厳密に一度の違い)が頻出です。Debezium 固有の挙動は直接問われにくいものの、CDC トピックをどう設計し、下流がどう受けるべきかは本質的に Kafka の設計問題です。
特に、キーの設計を問う設問、トピックのクリンナップポリシー選択、再処理時の重複と整合性の扱い、Connect のオフセット管理に関する理解が差になります。
CCDAK
問題 1
Debezium で RDB の行更新を Kafka に取り込んでいる。下流は ksqlDB のテーブルとしてアップサート集約する予定。最も適切なトピック設計はどれか。
正解: B
アップサート系の下流(テーブルセマンティクス)では、主キーでパーティショニングし、ログコンパクションにより同一キーの最新状態へ収束させるのが定石。delete 伝播には tombstone を使うため compact または compact,delete を用いる。
Schema Registry は必須ですか?
必須ではありません。プレーン JSON でも配信できます。ただし実務と CCDAK 両面で、スキーマ互換性の管理や進化が重要になるため、Avro/Protobuf/JSON Schema + Schema Registry の利用が推奨です。
スナップショット中の更新は失われませんか?
失われません。スナップショット完了後に、スナップショット期間中の変更をログで追随し適用します。最終的に Kafka トピックは後続イベントで整合します。
重複イベントは発生しますか?どう扱えばよいですか?
Kafka Connect の配信は少なくとも一度であり、再起動・リバランス等で重複があり得ます。キーに基づくアップサート、シンク側の冪等処理、トランザクションメタデータの活用で整合性を保ちます。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Kafka Topic と Partition の基礎: 分散とスケーラビリティの要
CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...
CCDAK 試験ガイド:出題範囲・配点・申込み・対策
Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...
Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点
CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...
Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性
レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...
Kafka の Offset とコミット: ポジション管理と at-least-once の基礎
CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...