Andrew Tanによる
Change Data Capture(CDC)は、リアルタイム分析やイベント駆動型システムを支える見えない層である——しかし、多くのチームは初めての本番インシデントを経験するまで、その存在を考えもしない。
すべてが依存する見えない層
リアルタイムダッシュボード。イベント駆動型マイクロサービス。常に最新の状態を保つデータレイク。これらの最新のデータアーキテクチャの背後には、多くのチームがあまり意識していないコンポーネントが存在する:Change Data Capture。
CDCの役割は単純だ——データベースのトランザクションログを監視し、データが変更されるたびにイベントを発行する。新規注文?イベントだ。ステータス更新?イベントだ。顧客削除?イベントだ。概念はエレガントで、動作していれば何の問題もない。
しかし、問題がある。CDCは現代のデータインフラの配管のようなものだ。正常に動作しているときは見えないし、失敗すると壊滅的で、なぜかアーキテクチャレビューではいつも後回しにされる。チームはKafkaのトポロジーやSparkの設定について何週間も議論し、そのあとでCDCコネクターをデフォルト設定のまま組み込んで先に進んでしまう。
6か月後、電話が鳴る。ダッシュボードは6時間遅れている。在庫同期は昨日のデータを表示している。CEOは、なぜ顧客が存在しない商品を購入できるのかと問い詰めている。そして誰も理由がわからない——モニタリングダッシュボードによれば、CDCコネクターは「正常」だからだ。
このパターンは業界全体で驚くほど一貫して繰り返されている。問題はCDCが根本的に信頼できないわけではない。チームが想定している動作と実際の動作の間に、インシデントがビジネス問題に発展するまで隠れてしまうほどの大きな乖離があるのだ。

CDCが実際に行うこと(そしてチームが想定していること)
その核心において、Change Data Captureはデータベースのトランザクションログを監視し、データが変更されるたびにイベントを発行する。行を挿入?イベントだ。フィールドを更新?イベントだ。レコードを削除?イベントだ。概念は見事にシンプルだ。
しかし、そのシンプルさは欺瞞的だ。以下は、CDCが実際に捉えているものと、チームが想定しているものの対比である:
| チームの想定 | 実際に起きていること |
|---|---|
| 「すべての変更は即座に捕捉される」 | レイテンシは存在する。ミリ秒の場合もあれば、秒単位の場合もあり、コネクターが滞留しているときはそれ以上遅れることもある。 |
| 「イベントはトランザクションと同じ順序で発行される」 | 必ずしもそうではない。並列レプリケーション、コミット順序、結果整合性により順序が入れ替わることがある。 |
| 「スキーマ変更は適切に処理される」 | 列を追加する場合は問題ない。しかし、列名を変更する場合は?列を削除する場合は?型を変更する場合は?CDCパイプラインに手動での介入が必要になることもある。 |
| 「ログを追跡しているだけで、何が問題になりうるのか?」 | コネクターのクラッシュ、レプリケーションスロットの枯渇、ソースDBのディスク容量問題、ネットワーク分断…… |
想定と現実の間の乖離こそが、インシデントを生む温床だ。
誰も語らない3つの障害モード
何十ものCDC導入が横道にそれるのを見てきた中で、チュートリアルやベンダーのデモでは十分に注目されていない3つの障害パターンに気づいた。
1. スキーマドリフトの罠
アプリケーションチームがordersテーブルに新しい列を追加した。NULL許容のdelivery_notesフィールドという、何の害もない変更だ。彼らは火曜日にデプロイした。すると木曜日までには、データウェアハウスに不完全なレコードが残っている。なぜなら、CDCコネクターはまだ古いスキーマを使用しており、新しいフィールドを静かにドロップしているからだ。
最悪なのは、コネクターが失敗しないことだ。生成されるイベントは技術的には有効だが、実用上は誤っている。スキーマバリデーターがすべて正常だと判断するため、データ品質モニターはこの問題を検出しない。週の半分にわたりdelivery notesのレポートが空白になっている理由を誰かに尋ねられるまで、その乖離に気づかない。
2. レプリケーションスロット爆弾
PostgreSQLユーザーの皆さん、これはあなたたち向けだ。CDCコネクターは、処理済みのWAL(Write-Ahead Log)エントリを追跡するために「レプリケーションスロット」を使用する。コネクターがダウンした場合——あるいは著しく遅くなっただけでも——これらのスロットはログエントリを保持し続ける。データベースはそのディスク領域を回収できない。
不安定なCDCコネクターがレプリケーションスロットを人質に取っていたため、本番データベースのディスク使用率が95%に達するのを目覚めて目にしたチームもある。修正策は、午前2時に実行するのが恐ろしく感じられる手動クリーンアップジョブだ。予防策は? 多くのチームが最初のインシデント後まで設定しない、モニタリングとアラートだ。
3. コンシューマー結合問題
CDCはイベントの奔流を発行する。データベースの変更を気にするあらゆるマイクロサービス、分析ジョブ、データウェアハウス同期が、そのストリームに接続する。それはエレガントで疎結合だ——そうでなくなるまでは。
遅いコンシューマーが1つ追いつけなくなったらどうなるか? Backpressureが伝播する。CDCコネクターはバッファリングし、次にイベントをドロップし、そしてクラッシュする。あるいはより悪いことに、実行し続けながら遅れを取り、誰も気づかないうちに「リアルタイム」パイプラインに20分の遅延が生じる。なぜなら、メトリクスダッシュボードには「コネクター正常」と表示されているからだ。
修正策は通常、CDCソースとコンシューマーの間に何らかのバッファリング(Kafka、Kinesis、メッセージキュー)を設けることだ。しかし、これによりレイテンシが追加され、管理するインフラも増える。単純な配管が、複雑なサブシステムになってしまう。
希望ではなく現実に合わせたサイジング
以下は架空の会話だ:
私:「CDCは1秒あたり何件のトランザクションを処理する必要がある?」
相手:「えーと、ピーク時でも数百件程度かな。」
私:「じゃあ、最大のテーブルはどれくらいの規模?」
相手:「約5,000万行くらい。」
私:「そのテーブルで一括更新を実行したらどうなる?」
相手:「……時々やることはある。」
CDCコネクターは平均的なトランザクション量向けにサイジングされるものではない。最悪ケースのトランザクション量向けにサイジングされるのだ。1,000万行に触れる四半期ごとのデータクリーンアップジョブ? それは一気に1,000万件のCDCイベントを生成する。コネクターがその急増に対応できなければ、遅延、Backpressure、またはイベントのドロップが発生する。
これをうまく行うチームは、初日からバーストを想定して計画する。コネクターの健全性だけでなく、レプリケーション遅延のモニタリングを設定する。障害モードをテストする:一括更新の途中でコネクターが再起動したらどうなる? 宛先が1時間ダウンしたらどうなる?
CDCを管理しやすくする設計判断
CDCは時限爆弾である必要はない。以下は、本番環境で機能したと私が確認しているパターンだ:
CDCインフラと分析インフラを分離する
CDCコネクターを、SparkジョブやBIクエリと同じクラスターで実行しないようにせよ。分析チームが重いJOINを実行してネットワークを飽和させたとき、CDCイベントが影響を受けるべきではない。CDC専用のレーンを確保する。
冪等なコンシューマーは譲れない条件
CDCイベントは重複しうる。コネクターが再起動し、ネットワーク分断が発生し、at-least-onceデリバリーがデフォルトだ。下流のコンシューマーが「この注文更新を2回処理する」ことを扱えなければ、データ破損が発生する。最初から冪等性を組み込む。
スキーマレジストリが正気を保つ
イベントスキーマの変更を追跡するために、スキーマレジストリ(Confluent Schema Registry、AWS Glueなど)を使用する。アプリケーションチームがテーブルを変更すると、スキーマ変更がレジストリを通じて反映され、コンシューマーは静かに壊れるのではなく、プログラムで適応できる。
重要なものをモニタリングする
「コネクターが実行中」は誤った指標だ。以下をモニタリングせよ:
- Replication lag(CDCがデータベースからどれだけ遅れているか?)
- Event processing rate(本番のペースに追いついているか?)
- Schema change events(ソースに知るべき変更があったか?)
- Dead letter queue depth(何が、なぜ処理できなかったか?)
layline.ioが担う役割:フットガンのないCDC
layline.ioでは、CDCに苦労するチームを数多く見てきたため、プラットフォームに専用のDebezium Source Assetを直接組み込んだ。目標はCDCを再発明することではない——Debeziumは優秀だ——本番システムに必要な信頼性と可観測性で包み込むことだ。
面倒を見る必要のあるスタンドアローンコネクターを実行する代わりに、layline.ioは以下を提供する:
Visual pipeline designで、CDCソースを第一級の要素として扱う。データベースから宛先までのデータフローを、1枚のキャンバス上で確認できる。何かが壊れたとき、正確にどこかがわかる。
Built-in backpressure handlingにより、Apache Pekkoのアクターモデルストリーミングを活用する。下流システムが遅くなったとき、layline.ioはイベントをドロップしたりコネクターをクラッシュさせたりするのではなく、優雅にスロットルする。
Unified retry and error handlingにより、パイプライン全体で一貫した再試行とエラー処理を実現する。処理に失敗したCDCイベントがログファイルに消えることはない——他のすべてのデータソースと同じ再試行メカニズムを通じて処理される。
Schema-aware transformationにより、手動介入なしにソースデータベースの変更に適応できる。列を追加しても、フィールド名を変更しても、型を変更しても——パイプラインは壊れるのではなく、調整される。
もっと広い視点で言えば、CDCを後付けのものにしておくには重要すぎる。CDCは、データインフラの他の部分と同じだけの技術的厳密さを値する。layline.ioを使っても、独自のスタックを構築しても、CDCをそれがそうである重要なコンポーネントとして扱え——地下室が水浸しになるまで無視できる配管のように扱うのではなく。
Andrew Tanは、layline.ioの創業者であり、大規模なバッチ処理とリアルタイム処理の両方に対応するエンタープライズデータ処理インフラを構築しているシリアルアントレプレナーです。



