Back to Blog
ArticleApril 27, 20267分

ソースシステムが予告なく変更されたとき、パイプラインに何が起こるか

スキーマドリフトと上流の破壊的変更は、サイレントデータ障害の主な原因です。予期せぬ事態に備える方法をご紹介します。

ソースシステムが予告なく変更されたとき、パイプラインに何が起こるか

Andrew Tanによる

スキーマドリフトと上流の破壊的変更は、サイレントデータ障害の主な原因です。これを防ぐ方法をご紹介します。


すべてを壊したフィールド

私が知っているフィンテック企業は、2年間美しく動作していた支払い処理統合を持っていました。1日に数十万件のトランザクション、堅固なパイプライン、満足する財務チーム。しかしある朝、調整レポートが意味不明なものを生成し始めました。収益の数字は桁違いにずれていました。正の数であるべきところが負の数になっていました。

根本原因の特定には6時間かかりました。彼らの支払い処理業者が、フィールド amount を文字列から整数に黙って変更していたのです。バージョンアップもなく、移行ガイドもなく、メールもなく。ただプッシュされただけでした。パイプラインの変換ロジックはそのフィールドで文字列操作を行っており、セントを切り取ったり、通貨コードを解析したりしていましたが、突然整数を受け取ったときにエラーは発生しませんでした。それは実行を続け、自動チェックを通過するのに十分なほどもっともらしい数字を生成しましたが、完全に間違っていました。

エンジニアの時間を6時間。財務チームの調整に2日間。CFOとの非常に不快な会話が1回。すべてはベンダーがフィールドの型を変更したためです。

私はこの話のバリエーションを数え切れないほど見てきました。ソースシステムが警告なしに変更されます。パイプラインはクラッシュしません。それはさらに悪いことをします:実行を続け、ゴミを生成します。

なぜこれが監視に現れないのか

ここで逆説的な部分があります。ほとんどのパイプラインは処理の失敗をキャッチするように設計されており、スキーマの失敗をキャッチするようには設計されていません。

ジョブが実行されないときにアラートが発生します。レイテンシが急上昇するときにアラートが発生します。宛先データベースが書き込みを拒否するときにアラートが発生します。入力が形を変え、処理ロジックが静かに横道にそれたときに通常アラートは発生しません。

その理由は構造的です。スキーマ検証は後回しにされる傾向があります。チームは最初にパイプラインロジックを書き、後で検証を心配し、実際には検証を実装しません。なぜなら、パイプラインはすでに実行されており、触るのがリスクだと感じるからです。

その結果、インフラストラクチャの障害に対しては戦闘力を持ち、データ契約違反には完全に盲目なシステムが出来上がります。

上流の変更の3つのクラス

すべての上流の変更が同じように危険なわけではありません。3つのカテゴリーがあります:

追加的な変更は友好的なものです。新しいオプションのフィールドが現れます。配列に新しいアイテムタイプが追加されます。ソースシステムが既存の構造を壊すことなく成長します。パイプラインはこれらをうまく処理します。必要のないものは無視するだけです。低リスクです。

破壊的な変更は明らかな敵です。必須フィールドが消えます。データ型が変わります。フィールドがリネームされます。これらは通常、ハードな失敗を引き起こしますが、実際には問題ありません。パイプラインがクラッシュし、アラートが発生し、修正します。痛みはありますが検出可能です。

サイレントな変更が最悪です。これらは失敗を引き起こさない変更です。フィールドはまだそこにあります。型は技術的には互換性があります。しかし、意味が変わっています。以前は "active""inactive" を含んでいた status フィールドが、今では "enabled""disabled" を含んでいます。ヌルチェックはまだ通ります。行数も正常に見えます。ダッシュボードもまだ表示されます。すべてが間違っています。

サイレントな変更はCFOとの会話に至るものです。

ほとんどのパイプラインが失敗する場所

本能的には、処理層での検証を追加したくなります。変換前に型をチェックします。必須フィールドが存在することを確認します。インジェスト時に形状チェックを実行します。

これは役立ちますが、核心的な問題を見逃しています。処理層での検証は型エラーをキャッチします。意味のドリフトはキャッチしません。フィールドが存在し、正しく型付けされ、意味が完全に間違っている場合をキャッチしません。

真の防御は、ソースシステムとパイプラインの間の契約にあります。

契約は、データの構造だけでなく、それに関する期待も定義します。フィールドXは少額単位で通貨を表す文字列です。フィールドYは正確にこれら4つの値を持つ列挙型です。フィールドZはUTCのタイムスタンプで、ヌルではなく、常に過去90日以内です。

その契約を明示的に定義し、すべてのインジェストでテストすることで、サイレントな変更が下流のデータを破壊する前にキャッチします。amount がまだ文字列であるが、今では少額単位ではなく全額を表す場合をキャッチします。列挙型がパイプラインが見たことのない5番目の値を持つ場合をキャッチします。

パイプライン層での契約テスト

契約テストはマイクロサービスでよく確立されています(Pactが最も一般的なフレームワークです)が、データパイプラインではあまり使われていません。基本的な考え方は簡単です:入力の形状と意味を正式な契約として定義し、その契約に対してデータが流れるたびにテストを実行します。

実際には、これは3つのことを意味します。

フィールド型を超えたスキーマ仕様。期待される値の範囲、カーディナリティ制約、フィールド間の関係を含めます。単に amount: integer ではなく、amount: positive integer, max 10,000,000, represents cents です。

これらのチェックを継続的に実行する監視レイヤー。パイプラインの起動時だけでなく。1回の実行で1つのチェックが失敗するのは問題ありません。500,000件のレコードで10,000件のチェックが失敗するのはサイレントな変更のアラームです。

データに合わせたアラート閾値。歴史的に0.1%のレコードがヌルの transaction_id を持っている場合(異常だが実際にある)、アラートを1%に設定します。ヌル率が1%に達したら、何かが変わりました。15%に達したら、何かが確実に変わりました。

実装する価値はありますか?はい、ただし1つの注意点があります:契約は統合の時点で書くべきであり、事後ではありません。既存のパイプラインに契約を後付けするのは苦痛です。なぜなら、何が真実であると仮定していたかを逆に解釈する必要があるからです。統合を最初に構築するとき、知識が新鮮なうちに期待を文書化するのが最適です。

各クラスに対する防御

追加的な変更:ただ無視します。必要なものだけを抽出するようにパイプラインを構築します。予期しないフィールドで壊れないようにします。

破壊的な変更:大声で速く失敗します。明確なエラーメッセージでのハードクラッシュは、サイレントな破損よりも良いです。依存するフィールドでのインジェスト時の厳密な検証。

サイレントな変更:これが契約テストの真価を発揮するところです。構造だけでなく分布を追跡します。status フィールドの値の分布が突然90% "active" / 10% "inactive" から50/50に変わった場合、上流で何かが変わりました。それが正当なビジネスの変化か、アカウントの分類方法の意味の変化かはわかりません。いずれにせよ、知りたいことです。

layline.ioがこれをどのように処理するか

ほとんどのパイプラインフレームワークの課題は、スキーマの変更がパイプラインの変更を必要とすることです。フィールドマッピングを更新し、ジョブを再デプロイし、他に何も壊れないことを祈ります。"上流が変わった" と "パイプラインが適応した" の間のフィードバックループは数時間または数日です。

layline.ioでは、処理モデルが論理的な作業(データで何をしたいか)と物理的な形式(データがどのような形で到着するか)を分離しています。スキーマの進化、新しいフィールド、リネームされたフィールド、型の変更は、コードではなく設定を通じて処理できます。論理フィールドが物理スキーマからマッピングされるため、物理スキーマが変わると、パイプラインを書き直すことなくマッピングを更新します。

これにより、契約テストの必要性がなくなるわけではありません。予期しないものが到着したときに知りたいことは変わりません。しかし、影響範囲を劇的に減少させます。パイプラインの書き直しと再デプロイを必要とする上流の変更が、数分で済む設定の更新になります。

また、同じソースシステムに対してバッチとストリーミングの両方の統合を同じスキーマ処理で実行できることも意味します。支払い処理業者がフィールドを変更したとき、それを1回修正すれば済みます。あなたのリアルタイム不正検出パイプラインと夜間の調整バッチジョブを別々に修正する必要はありません。

実用的なポイント

持っていない契約から始めましょう。サイレントなデータ変更が最も大きな被害をもたらす3つの最も重要な上流の統合を選び、各フィールドから実際に何を期待しているかを書き出します。型だけでなく、範囲、許可される値、意味の意味も含めます。

次に、その期待からの逸脱をキャッチする監視を構築します。完璧ではなく、広範囲ではなく、まず最も重要な統合から始めます。

ほとんどのチームは、何かが壊れるまで明示的な契約なしで運営しています。契約を持って運営しているチームは、上流の変更を自分たちの条件で知ることができます。腐敗したデータで午前3時にではなく。


Andrew Tan はシリアルアントレプレナーであり、layline.io の創設者であり、バッチとリアルタイムの両方のワークロードを大規模に処理するエンタープライズデータ処理インフラストラクチャを構築しています。

Share:

Enjoyed this article?

Subscribe to get more insights delivered to your inbox.