PostgreSQLのトランザクションログに接続されたDebeziumコネクタを使用して、Change Data Capture(CDC)レイヤーを実装します。メッセージの耐久性と保持を確保するために、Apache Kafkaを通じてイベントをストリーミングし、ログコンパクションを有効にします。
Apache FlinkまたはksqlDBをデプロイして、状態保持型ストリーム処理を行い、S3またはGCSへのチェックポイントを介してexactly-once semanticsを維持します。AvroまたはProtobufフォーマットを使用してConfluent Schema Registryを使用し、進化の際に消費者の壊れを防ぐための後方および前方の互換性ルールを強制します。
矛盾を解決するために、地域間の因果関係を追跡するためにメタデータレイヤーにVector ClocksまたはVersion Vectorsを実装します。重要でないフィールドにはLast-Write-Wins(LWW)を適用し、カウンターとセットにはCRDTベースのマージ関数を使用します。分析のために最終的なビューをClickHouseまたはApache Druidにマテリアライズし、ビューのストアにおける最終的一貫性を確保するために、NarayanaやSagaパターンのような分散トランザクションコーディネーターを使用してACIDプロパティを確保します。
GlobalMartという国際的なeコマースプラットフォームは、ブラックフライデーイベント中に重要なデータの古さに直面しました。彼らの夜間バッチETLジョブは、MySQLのトランザクション記録とBigQuery分析ダッシュボードの間に4時間の遅延を生じさせ、在庫の過剰販売と価格更新の失敗を引き起こしました。
ソリューションA:検索インデックスへの直接CDC。 彼らはLogstashを使用してMySQLのbinlogを直接Elasticsearchにストリーミングすることを検討しました。これにより低遅延と簡単なセットアップが可能でした。しかし、テーブル間の複雑な結合操作は不可能になり、スキーマの変更には全体のElasticsearchの再インデックスが必要となり、6時間のダウンタイムが発生しました。
ソリューションB:コマンドクエリ責任分離(CQRS)によるイベントソーシング。 このアプローチは、読み取りモデルと書き込みモデルを分離するためにAxon Frameworkを使用しました。優れた監査トレイルと柔軟性を提供しましたが、アプリケーションの完全なリファクタリングが必要でした。チームの既存のモノリシックなSpring Bootアプリケーションはイベントソーシングに簡単に移行できず、学習曲線は2ヶ月の締切には急すぎました。
ソリューションC:スキーマレジストリを使用したストリーミングマテリアライズドビュー。 彼らはPostgreSQLからDebeziumを使用して取得し、Kafkaにストリーミングし、ビジネスロジックを適用してFlinkによって処理し、最終的にClickHouseに沈めました。Confluent Schema RegistryのAvroスキーマは、CI/CD中の互換性チェックを強制しました。矛盾解決には、地域のプロモーションが異なる在庫カウントを引き起こした際に自動マージを可能にするためにKafkaヘッダーに埋め込まれたVector Clocksを使用しました。
彼らはソリューションCを選択しました。これは既存のSQLスキーマを維持しながらリアルタイムの能力を可能にしました。Schema Registryはカナリアリリース中に互換性のないスキーマ変更を拒否することによってデプロイ失敗を防ぎました。
結果として、エンドツーエンドで120msの遅延を達成し、1秒あたり50,000のトランザクションをサポートし、us-east-1地域の停止中にセカンダリ地域のKafkaミラーメーカー2セットアップにフェイルオーバーすることでRPOゼロを維持しました。
CDCは、マテリアライズドビューでの部分的更新を防ぐために、どのようにマルチテーブルのトランザクション整合性を処理しますか?
多くの人は、Debeziumがテーブル全体で自動的にアトミック性を保証すると仮定していますが、実際にはCDCはテーブルごとに別々のイベントを発信します。整合性を維持するためには、ビジネスロジックと同じデータベーストランザクション内にビジネスイベントを書き込むTransactional Outboxパターンを実装する必要があります。Debeziumはアウトボックステーブルのみをキャプチャして、アトミックイベントの発信を確保します。代わりに、Debeziumのtransaction.metadata機能を使用して、トランザクションIDでイベントをグループ化し、すべての関連イベントが到着するまでバッファリングしてからビューを更新します。
地域横断ビューに対して、いつeventual consistencyをstrong consistencyの代わりに選択し、具体的な実装のトレードオフは何ですか?
候補者は遅延コストを考慮せずに強整合性にデフォルトで進むことが多いです。強整合性は、2地域間でのTwo-Phase Commit(2PC)またはPaxos/Raftコンセンサスを必要とし、書き込みごとに100-300msの遅延を追加します。これは財務台帳や在庫割り当てには必要です。推奨エンジンや分析ダッシュボードの場合、CRDTやlast-write-winsを使用します。トレードオフは、クライアント側のマージロジックの複雑さとサーバー側の調整の複雑さです。CRDTは不変のデータ構造と可換操作を必要とし、ビジネスロジックの柔軟性が制限されますが、パーティショニング中の可用性を提供します(CAP定理におけるAP)。
非推奨フィールドを削除する際に、スキーマ進化が下流の消費者を壊すのをどのように防ぎますか?
ほとんどの人は前方互換性(新しいコードが古いデータを読み取る)を理解していますが、後方互換性(古いコードが新しいデータを読み取る)を見落としています。フィールドを削除する際は、すぐに削除しないでください。代わりに、Schema RegistryのAvroのdefault値を使用し、新しいスキーマで消費者を展開し、2つのリリースサイクル後にプロデューサーでフィールドの書き込みを停止します。破壊的な変更(例:型変更)の場合は、Schema Evolution via Separate Topicsを実装します:events-v2トピックに書き込みながら、ブリッジ消費者を持つevents-v1を維持することで、ダウンタイムなしに徐々に移行を可能にします。