0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Postgres CDC→Iceberg:リアルワールドの課題を徹底解剖

Posted at

Postgres CDC→Iceberg:リアルワールドの課題を徹底解剖

過去一年間、データ基盤業界はほとんど PostgresApache Iceberg に注目が集中していました。Databricks による Neon の買収、Snowflake による CrunchyData の買収は、この二方向への業界の評価をさらに確固たるものにしています。Postgres はすでに OLTP 分野の事実上の標準 としての地位を確立し、Iceberg はオープンなテーブル形式と広範なエコシステムの支えにより、一部のプロプライエタリなクラウドデータウェアハウスを置き換えつつあり、モダンなデータレイクの中心的選択肢 になりつつあります。

しかし、これら二つをリアルタイムでつなぐという課題は依然として残っています。Iceberg テーブルに Postgres のリアルタイム変更データを継続的に同期するには、CDC(Change Data Capture)パイプラインが不可欠です。業界で広く使われている Debezium や Kafka Connect は長年存在しており、一見「解はある」ように見えます。私もそう考えていました。

しかし、実際のプロダクション事例を詳細に分析し、複数のエンジニアリングチームと深く議論を重ねた結果、私が見つけたのは:Postgres CDC から Iceberg へのリアルタイムなデータ取り込みは、決して「解決済みの問題」ではないという現実です。上流のデータ取得、下流のデータ書き込み、いずれにおいても看過できない細部の問題が潜んでいます。これらの課題は次のような領域に集中しています:

  • エンドツーエンドでの Exactly Once セマンティクス保証
  • 障害からの復旧メカニズム
  • スナップショットとバックフィルの性能
  • スキーマ進化への対応
  • Iceberg 書き込みの整合性保証
  • 複雑な多コンポーネント運用アーキテクチャ

以下、それぞれのチャレンジを分解し、現場に基づく具体的な経験と教訓を共有します。


1. Exactly Once 保障と障害対応

信頼性のある CDC パイプラインを構築するにあたり、最初の最大の課題は エンドツーエンドでの Exactly Once セマンティクスを実現すること です。多くのツールは At Least Once にとどまり、概念上は許容できても、実際にプロダクション障害が起こると、重複データ、データ欠損、手動による再投入などの問題が明るみに出ます。

上流障害からの復旧

Postgres の replication slot は堅牢に設計されていますが、プロダクション環境では極端なトラブルが起こり得ます。Postgres のクラッシュやネットワーク遮断、あるいは WAL 保持ポリシーによる replication slot の消失などが起きた場合、多くの CDC ツールでスムーズな復旧が困難になります。よくある典型的な問題としては、CDC リーダー(例:Debezium)と下流処理との間で ログシーケンス番号(LSN)のオフセットがずれてしまうことです。復旧ポイントが正確でないと、イベントの欠落や重複送信が起こります。

実際、多くのチームが replication slot を喪失した際、データベースの全量スナップショットを再取得する必要に迫られました。数百 GB〜TB に及ぶデータ規模では、全量スナップショットは時間・コストともに大きく、さらにテーブルロックを伴えばオンライン業務への影響は深刻です。

ある e コマース企業では、Debezium を使って Postgres に接続していましたが、一時的なデータベース停止で replication slot が失われ、最終的に全テーブルのスナップショットを再実行する羽目になり、復旧までにほぼ10時間を要しました。その間、大量の I/O を消費し、データ分析チームは待機状態に。ビジネスもほぼ停止していました。


下流障害隔離(下流系の故障分離)

Iceberg や Snowflake 側でも書き込み失敗や一時的な可用性欠如が発生する可能性があります。もし内部にバッファリングやフロー制御がなければ、多くの CDC パイプラインはブロックされがちです。Kafka のトピックが保持期間を超えて蓄積されると、データ欠失か再処理かという選択を迫られ、最終的には手作業での補完や再同期に回帰してしまいます。

ある企業では、AWS S3 の一時的な障害により Iceberg Sink が継続的に失敗し、結果として Debezium や Kafka のメッセージが堆積。上流に back‑pressure が伝播し、Postgres 側で Debezium が low LSN を昇格できず、WAL ログがどんどん溜まっていった結果、replication lag が巨大化。気づいたときには WAL がディスクをほぼ占有し、メインデータベースを危うく破綻させるところでした。このような“連鎖反応”は典型的な CDC パイプラインの悪夢であり、多くのチームが Debezium を使用する際に見落としがちなリスクです。


エンドツーエンドの Exactly Once の難しさ

Debezium、Kafka、Flink などの各コンポーネントが checkpoint やリトライ機構を持っていても、それらをつなぎ合わせて完全な エンドツーエンドの Exactly Once を実現するのは簡単ではありません。コンポーネント間の受け渡し点において、重複処理や欠落処理のリスクが残ります。特に backfill(バックフィル)フェーズではこの傾向が顕著です。

特に問題となるのが、スナップショット(snapshot)フェーズと WAL による増分ログの整合です。

最も簡単な方法としては、スナップショット取得時に上流テーブルをロックし、その間の新規書き込みを防いでから WAL 消費を開始し、最後にロックを解除するというものです。この方法は整合性を保証しますが、当然ながら上流写入をブロックするため、大多数のオンライン業務には不適です。

ロックを避ける場合、次のような難題に直面します:スナップショット中に上流で追加されたデータを、漏れなく読み取りつつ重複させずに処理しなければならない ということです。

RisingWave や Flink CDC のようなシステムでは、スナップショット取得と並行して WAL の読み取りを続け、下流で状態テーブルを使って snapshot と WAL のデータを対応付けることで、一切データを失わず、かつ上流書き込みを阻害しない方法を採用しています。

また、復旧や再起動のケースでは、高整合性な checkpoint 機構が欠けていたり、checkpoint が Kafka offset と緻密に同期されていない場合、データの過読みや過少読み込みが起こる可能性があります。WAL offset を厳密に管理することが、Exactly Once の保証の鍵であり、これは上位の CDC エンジン自身が持つべき責務です。

さらに、Iceberg 側には特有のチャレンジがあります。Iceberg は自動的に主キー単位の冪等更新(idempotent update)をサポートしていません。単純に append やバッチ書き込みだけを行い、equality delete や merge‑on‑read モード を使っていないと、重複レコードが容易に発生します。一旦そのような重複がディスクに書き込まれると、以後のクリーンアップに非常に大きなコストがかかります。

特に金融やコンプライアンスに関わる業務では、このような問題は許容できません。ある取引企業の CDC パイプラインを調整していた際、スナップショットと増分データの復旧時の整合がうまく取れず、加えて Iceberg 側で冪等性が正しく扱われなかったため、下流での資金残高計算に誤差が生じました。最終的には、Iceberg テーブル上に複雑な重複排除ロジックを追加する必要があり、パイプラインの運用負担と遅延が増大しました。


2. 性能とリソース消費

CDC パイプラインの性能上の課題は、PoC(概念実証)から本番導入に移行した段階で初めて顕在化することが多いです。CDC ツールは、初回スナップショット継続的な増分変更処理 の両方に対応しなければならず、それぞれに異なるチャレンジがあります。

Replication Slot のリソース圧力

Postgres の replication slot は有限リソースです。実際の本番環境では、多くの場合「1 つのデータベースに対して 1 つの replication slot」という構成が一般的で、テーブルごとに個別に作成するわけではありません。たとえば RisingWave の実装では、共有ソース(shared source)が 1 つの上流 Postgres インスタンスに対応し、同一の replication slot を共有しています。

しかし、Debezium などがマルチテナント環境やマルチインスタンス構成で導入されている場合、設定によっては各コネクタまたは各購読シナリオごとに slot を作成してしまい、slot 数が過多になって WAL ログの整理や Vacuum 操作が滞ることがあります。長期間にわたる WAL の蓄積はディスクを圧迫し、さらには I/O 負荷の増大も招きます。

ある顧客では、データベースには実質的に 2 つの replication slot しか存在しなかったものの、Debezium の消費速度が WAL の生成に追いつかず、数百 GB の WAL が溜まり、アーカイブ処理が追いつかないという事態が発生しました。最終的には、Debezium の処理速度を一時的に引き上げ、手動で WAL をクリアすることで事態は落ち着きました。


スナップショットとバックフィルの性能ボトルネック

初回スナップショットは、ほとんどのチームが直面する最大の課題です。従来の CDC ツールは、スナップショット時に単一スレッドで順次スキャンする方式を採用していることが多く、この方式では数億行以上の大規模テーブルでは非常に時間がかかり、数時間から数日に及ぶことも珍しくありません。途中で失敗すると最初からやり直すしかなく、時間もリソースも無駄になります。

さらにやっかいなのが、スナップショットと WAL 増分データの整合性合わせです。整合性を保とうとすれば、スナップショット取得時に上流テーブルをロックし、新規書き込みを防ぐ必要がありますが、これはオンライン業務にとって致命的です。

RisingWave や Flink CDC は、スナップショット中も並行して WAL を読み取り、下流の状態テーブルで snapshot と WAL を丁寧に突き合わせる方式を採用しており、それによりデータの欠落も、上流への影響も回避可能にしています。

ある SaaS 企業では、Debezium による移行を試みたところ、大規模テーブルのスナップショットがオンライン OLTP 性能を著しく低下させ、夜間に業務を停止してスナップショットを毎晩実行する必要が生じました。本来なら2日で終わる作業が、結局1週間かかって完遂した例もあります。


大規模フィールドのメモリ使用問題

Postgres の TOAST フィールド(例えば巨大 JSON オブジェクトなど)も課題となります。Debezium は読み込み時にこれらの大きなフィールドを一度にメモリにロードする傾向があり、複数の大トランザクションが並行処理されるとメモリが枯渇する OOM(Out Of Memory)問題が現実に起こります。多くのチームでは、フィールド分割やデータ圧縮などの方法で一時的に対応しています。


3. データ型とスキーマ進化(Schema Evolution)

スキーマ変更は CDC パイプラインにおいて最も軽視されがちなチャレンジです。現代の Postgres では、フィールド追加、型変更、インデックス再構築などのスキーマ変更が頻繁に行われます。これらの変更が CDC チェーンに伝搬すると、下流データの不整合やパイプラインの破綻につながることがあります。

パーティションテーブルと TOAST サポート

Debezium はパーティションテーブルと TOAST フィールドへの対応が不十分です。TOAST フィールドを正しく扱うには full replica identity モード を有効にする必要がありますが、これにより WAL サイズが大幅に増加します。また、パーティションテーブルに新しいパーティションが追加されても自動的に検出されないため、Connector を再起動する必要がある場面があり、大きなリスクとなります。


複数下流環境へのスキーマ進化対応

Iceberg や Snowflake、Redshift など複数の下流に同時にデータを同期する場合、スキーマ進化の対応はさらに挑戦的です。Postgres に列を追加しただけで、以下のような作業が必要になりがちです:

  • Debezium の設定変更
  • Kafka Schema Registry の更新
  • Flink バッチ/ストリームジョブの修正
  • Iceberg テーブルのスキーマ変更

多くのチームはスキーマ同期用の自動化ツールを構築しますが、型不一致やデフォルト値の欠落など、ちょっとしたミスが不整合を引き起こします。


4. Iceberg 書き込みと整合性

Iceberg はバッチ処理向きに設計されており、一方 CDC ストリーム処理は行レベルでの継続的変更です。これら二つをどのようにバランスさせるかは重要な課題です。

バッチコミットとトランザクション境界

CDC イベントは通常、バッチにまとめたうえで Iceberg に書き込みます。しかし、バッチのコミットが失敗すると、Iceberg 自体には自動ロールバック機構がないため、部分的な書き込みが残る可能性があります。この場合、失敗バッチを検出して再実行する仕組みを別途組まなければ、データ欠損や重複が発生するリスクがあります。


小ファイル問題とコンパクション

もう一つの典型的な課題は 小パーケットファイルの大量生成です。コミットが頻繁すぎると非常に細かい Parquet ファイルが乱立し、Iceberg のメタデータ層は数千〜数万のファイルを管理せねばならず、クエリ性能が著しく低下します。多くのチームはコンパクション処理を追加することで対応しますが、それに伴う遅延や運用負担が増大します。


5. 運用の複雑さ

最後に、Postgres から Iceberg への CDC パイプラインは運用上極めて複雑になります。典型的なアーキテクチャは以下のような構成です:Debezium による CDC 抓取 → Kafka によるバッファ → Flink による変換 → カスタム Iceberg Sink への書き込み。各フェーズが独立して監視・調整・復旧可能である必要があります。

あるチームでは、ほとんど専属の SRE チームがこの CDC システムを「育てる」状態でした。障害対応の際は Debezium、Kafka、Flink と複数のログを行き来し、それぞれに offset や checkpoint があるため、Connector を再起動するだけでもデータの重複または欠損を引き起こすリスクがあります。


RisingWave のアプローチ

RisingWave は、これらの課題に対処するために登場した、統一された解決策を提供するストリーミングデータベースです。Postgres から CDC データを直接取得し、エンドツーエンドで Exactly Once セマンティクスを保証しつつ Iceberg に安全に書き込むことを目指しています。

CDC 取得の層では、RisingWave は Debezium Embedded Engine を WAL 解析エンジンとして採用していますが、実運用で多数の最適化を行いました。Debezium は高スループット・低レイテンシなリアルタイムパイプライン用途には設計されておらず、特に大トランザクションや複雑なスキーマ進化、offset 管理に多くの課題があります。RisingWave による改良点には以下が含まれます:

  • 大量トランザクション・高並行シーンに対応した WAL 解析とメモリ管理の改善。メモリ使用量を大幅に削減。
  • offset 管理と LSN 永続化ロジックの最適化。障害時でも正確な位置から消費を再開可能。
  • 複雑なスキーマ変更にも対応できるスキーマ解析性能の向上。遅延の削減。
  • Debezium を RisingWave 内部の log storestate table に緊密統合。snapshot と WAL の精密な整合を実現。

全体設計のキー特性として、RisingWave は以下の機能を備えています:

  • 強力な障害復旧能力:内部の LSN 管理により、障害発生時でもスムーズに復旧可能。再スナップショット不要。
  • 下流の分離:永続化された log store を活用し、下流の Iceberg に障害が起きても、上流の CDC 採取は継続可能。復旧後に順序通りに補填。
  • 高効率スナップショット無ロック並列スナップショット を提供し、OLTP 業務への影響を最低限に抑えつつ全量ロード時間を大幅短縮。
  • ネイティブ Iceberg サポート:バッチ書き込み、Equality Delete、トランザクションコミット、自動コンパクション対応。
  • スキーマ自動進化対応:上流のスキーマ変更を自動検知/同期し、人為的な調整を削減。
  • 使いやすさと可観測性:1つのシステムで CDC 捕捉、ストリーム変換、Iceberg 書き込みを完結。Debezium‑Kafka‑Flink の複雑構成を不要に。

总结(まとめ)

一見すると、Postgres CDC から Iceberg へのリアルタイム連携は「すでに解決された課題」のように見えますが、実際にはそうではありません。上流レプリケーションの複雑さ、スナップショットおよびバックフィルの性能ボトルネック、スキーマ進化による不整合、Iceberg 書き込み時のトランザクション保証、そして複数コンポーネントによる運用負荷といった要素が、この問題を依然として難題にしています。

RisingWave の目的は、これらすべてを徹底的に簡潔化することです。

CDC 捕捉、ストリーミング変換、Iceberg 書き込みを一体化したシステムにより、RisingWave は 高信頼性、低レイテンシ、エンドツーエンドの Exactly Once セマンティクス を実現し、さらに 自動スキーマ変更対応 を提供します。上流の Postgres テーブル構造がどのように進化しても、RisingWave はその変化を自動的に検知し、下流の Iceberg まで一貫して反映します。Debezium 設定の調整、Kafka Schema Registry や下流表構造の手作業による変更といった煩雑さを排除します。

典型的な事例として Siemens(西門子) を挙げることができます。

RisingWave 導入前、Siemens では SQL Server CDC を使い、SQLServer → Debezium → Kafka → RisingWave というパイプラインを運用していました。この構成では、複数の Debezium 設定パラメータを維持する必要があり、Kafka やその offset 管理も含めて複雑かつトラブル耐性が低い構成でした。

商用版の RisingWave を導入後、彼らの CDC パイプラインは RisingWave が直接上流 SQL Server に接続する形に簡略化され、Debezium の複雑な設定も不要、Kafka リンクを明示的に管理する必要もなくなりました。ユーザーから見ると Debezium や Kafka の存在は完全に意識されず、RisingWave が CDC データを「箱から出してすぐ使える」ようなブラックボックスとして機能し、運用コストとトラブルリスクが大幅に削減されました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?