CDC (変更データキャプチャ) の概要 変更データ キャプチャ (CDC) は、データベース操作 (挿入、更新、削除) の行レベルでの変更を追跡し、イベントの順序に従って他のシステムに通知するために使用される手法です。災害復旧シナリオでは、CDC は主にプライマリ データベースとバックアップ データベース間でデータを同期し、プライマリ データベースからセカンダリ データベースへのリアルタイムのデータ同期を可能にします。 source ----------> CDC ----------> sink アパッチ シートンネル CDC SeaTunnel CDC は、次の 2 種類のデータ同期を提供します。 : テーブルから履歴データを読み取ります。 スナップショット読み取り : テーブルから増分ログの変更を読み取ります。 増分トラッキング ロックフリーのスナップショット同期 Debezium などの既存の CDC プラットフォームの多くは、履歴データの同期中にテーブルをロックする可能性があるため、ロックフリーのスナップショット同期フェーズが強調されています。スナップショット読み取りは、データベースの履歴データを同期するプロセスです。このプロセスの基本的な流れは次のとおりです。 storage -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/ 分割パーティション (分割ディストリビューター) は、指定されたフィールド (テーブル ID や一意のキーなど) と定義されたステップ サイズに基づいて、テーブル データを複数の分割に分割します。 splitEnumerator 並列処理 各分割は、並列読み取りのために異なるリーダーに割り当てられます。 1 つのリーダーが 1 つの接続を占有します。 イベントフィードバック 分割の読み取り操作が完了すると、各リーダーは進行状況を に報告します。分割のメタデータは次のように提供されます。 splitEnumerator String splitId # Routing ID TableId tableId # Table ID SeatunnelRowType splitKeyType # The type of field used for partitioning Object splitStart # Start point of the partition Object splitEnd # End point of the partition リーダーは分割情報を受け取ると、適切な SQL ステートメントを生成します。開始する前に、現在の分割の対応する位置をデータベース ログに記録します。現在の分割が完了すると、リーダーは次のデータを使用して進行状況を に報告します。 splitEnumerator String splitId # Split ID Offset highWatermark # Log position corresponding to the split, for future validation 増分同期 増分同期フェーズは、スナップショット読み取りフェーズの後に開始されます。この段階では、ソース データベースで発生した変更がすべてキャプチャされ、バックアップ データベースにリアルタイムで同期されます。このフェーズでは、データベース ログ (MySQL binlog など) をリッスンします。増分トラッキングは通常、binlog の重複プルを回避し、データベースの負荷を軽減するためにシングル スレッドで行われます。したがって、使用されるリーダーは 1 つだけで、単一の接続を占有します。 data log -------------> splitEnumerator ---------- split ----------> reader ^ | | | \----------------- report -----------/ 増分同期フェーズでは、スナップショット フェーズのすべての分割とテーブルが 1 つの分割に結合されます。このフェーズでの分割メタデータは次のとおりです。 String splitId Offset startingOffset # The lowest log start position among all splits Offset endingOffset # Log end position, or "continuous" if ongoing, eg, in the incremental phase List<TableId> tableIds Map<TableId, Offset> tableWatermarks # Watermark for all splits List<CompletedSnapshotSplitInfo> completedSnapshotSplitInfos # Snapshot phase split details フィールドは次のとおりです。 CompletedSnapshotSplitInfo String splitId TableId tableId SeatunnelRowType splitKeyType Object splitStart Object splitEnd Offset watermark # Corresponds to the highWatermark in the report 増分フェーズの分割には、スナップショット フェーズのすべての分割のウォーターマークが含まれます。最小のウォーターマークが増分同期の開始点として選択されます。 正確に 1 回だけのセマンティクス スナップショット読み取りフェーズでも増分読み取りフェーズでも、データベースは同期のために変更される可能性があります。正確に 1 つの配信を保証するにはどうすればよいでしょうか。 スナップショット読み取りフェーズ たとえば、スナップショットの読み取りフェーズでは、行 の挿入、 の更新、 の削除などの変更が発生している間に分割が同期されます。読み取りプロセス中にタスク識別が使用されない場合、更新が失われる可能性があります。SeaTunnel はこれを次のように処理します。 k3 k2 k1 まず、分割を読み取る前に、binlog の位置 (低ウォーターマーク) を確認します。 範囲 内のデータを読み取ります。 split{start, end} 読み取り後の最高水準点を記録します。 場合、分割されたデータは読み取り中に変更されていません。 場合、処理中に変更が発生しています。このような場合、SeaTunnel は次の処理を実行します。 high = low (high - low) > 0 分割されたデータをメモリ内のテーブルとしてメモリにキャッシュします。 主キーを使用してメモリ内テーブルで操作を再生し、 から まで順番に変更を適用します。 low watermark high watermark 最高水準点を報告します。 insert k3 update k2 delete k1 | | | vvv bin log --|---------------------------------------------------|-- log offset low watermark high watermark CDC reads: k1 k3 k4 | Replays v Real data: k2 k3' k4 増分フェーズ 増分フェーズを開始する前に、SeaTunnel はまず前のステップからのすべての分割を検証します。分割間ではデータが更新されることがあります。たとえば、split1 と split2 の間に新しいレコードが挿入された場合、スナップショット フェーズでそのレコードが失われる可能性があります。分割間でこのデータを回復するために、SeaTunnel は次のアプローチに従います。 すべての分割レポートから、ログの読み取りを開始するための開始ウォーターマークとして最小のウォーターマークを見つけます。 読み取られたログ エントリごとに、 をチェックして、データが分割で処理されたかどうかを確認します。処理されていない場合は、分割間のデータと見なされ、修正する必要があります。 completedSnapshotSplitInfos すべての分割が検証されると、プロセスは完全な増分フェーズに移行します。 |------------filter split2-----------------| |----filter split1------| data log -|-----------------------|------------------|----------------------------------|- log offset min watermark split1 watermark split2 watermark max watermark チェックポイントと再開 CDC を一時停止および再開するにはどうすればよいでしょうか? SeaTunnel は分散スナップショット アルゴリズム (Chandy-Lamport) を使用します。 システムに 2 つのプロセス と があり、 には 3 つの変数 があり、 には 3 つの変数 があるとします。初期状態は次のとおりです。 p1 p2 p1 X1 Y1 Z1 p2 X2 Y2 Z2 p1 p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3 この時点で、 グローバル スナップショットを開始します。 最初にプロセス状態を記録し、次に にマーカーを送信します。 p1 p1 p2 マーカーが に到達する前に、 メッセージ を に送信します。 p2 p2 M p1 p1 p2 X1:0 -------marker-------> X2:4 Y1:0 <---------M---------- Y2:2 Z1:0 Z2:3 マーカーを受信すると、 状態を記録し、 メッセージ を受信します。 すでにローカル スナップショットを実行しているため、メッセージ をログに記録するだけで済みます。最終的なスナップショットは次のようになります。 p2 p1 M p1 M p1 M p2 X1:0 X2:4 Y1:0 Y2:2 Z1:0 Z2:3 SeaTunnel CDC では、マーカーはすべてのリーダー、分割列挙子、ライター、およびその他のノードに送信され、それぞれがメモリ状態を保持します。