歴史: 従来のeコマースプラットフォームは、悲観的ロックを使用したモノリシックなRDBMSインスタンスに依存しており、1秒あたり10万件を超える同時チェックアウトのフラッシュセールの負荷に耐えられなくなりました。 業界は、読み取りパスと書き込みパスを切り離すためにCQRSやイベントソーシングパターンにシフトしましたが、これにより、さまざまな待機時間特性を持つ分散WMSと年次ERPサイロ間での在庫精度の維持に複雑さが生じました。
問題: コアの課題は、ネットワークの分割中にCAP定理の制約を満たしながら過剰販売を防ぐこと—これは厳しいビジネスの不変量です。RedLockのような分散ロックメカニズムは、待機時間と可用性のリスクを引き起こし、一方で純粋な最終的整合性モデルは、ファントム在庫の販売のリスクを抱えています。さらに、レガシーSOAP/XMLベースのWMSシステムとの異種の統合ポイントはインピーダンスミスマッチとタイムアウトのカスケードを生み出し、原子トランザクション境界を複雑にします。
解決策: (例: Apache KafkaまたはEventStoreDB)として、在庫デルタの真実の源としてイベントストアを実装し、グローバルロックなしで因果関係の順序を確立するために楽観的同時制御とベクトルクロックを使用します。Sagaオーケストレーション(TemporalまたはCamundaを使用)を導入し、クロスWMSトランザクションを管理し、ローカルの予約が直ちにイベントストアにコミットされ、WMSからの非同期確認が最終的な配分または補償リリースをトリガーします。読み取りスケーラビリティのために、Debeziumを介してCQRSをCDCとともに展開し、RedisまたはElasticsearchにプロジェクトし、サブ50msの読み取り待機時間を確保し、一時的な古さを予約のTTLによって軽減します。
2022年のブラックフライデーの準備中、あるグローバルファッションリテイラーが、50,000人の同時ユーザーが限定版スニーカーのリリースを狙った際に壊滅的なデータベースタイムアウトを経験しました。彼らの既存のMySQLのマスター-スレーブトポロジーは、ホットな在庫行で深刻な書き込み競合に苦しみ、12秒のチェックアウト待機時間と、プライマリと読み取りレプリカ間のレプリケーション遅延によって引き起こされた300件の確認済みの過剰販売インシデントが発生しました。ビジネスは、売れるユニットが常に物理的倉庫在庫を超えないという厳格な不変量を維持しながら、フラッシュセールのトラフィックの津波を吸収できるソリューションが必要でした。
エンジニアリングチームは、在庫の減少中に分散相互排除を強制するために、3つの可用性ゾーン全体でRedis RedLockアルゴリズムを実装することを提案しました。このアプローチは、チームの既知の強い整合性の保証の利点と、既存のRedisクラスターとの簡単な統合を提供しました。しかし、重大な欠点は、可用性ゾーンの障害時に500msを超える許容できない待機時間のスパイクであり、ロックの安全性の特性を無効にする可能性のあるクロックのずれにより、最も重要な収益を生むウィンドウ中の在庫配分がデッドロックされるリスクがありました。
別の戦略は、SKU範囲による垂直シャーディングをデータベースに適用し、地域のPostgreSQLインスタンス全体で2PCプロトコルを用いてACID保証を維持することでした。このソリューションは、強い整合性と即時の在庫精度を提供したものの、複雑な最終的一致パターンを必要とせず、伝統的なトランザクション的思考に適していました。それでも、欠点は許容できないものでした: 2PCのブロッキング性により、コーディネーターの故障がデータベースロックを無期限に保持する可能性があり、プロトコルのメッセージの複雑さがトラフィックのピーク時にネットワークの飽和を引き起こし、24/7のグローバル商取引に必要な可用性要件を根本的に侵害しました。
最終的な候補アーキテクチャは、Apache Kafkaとサガオーケストレーションを使用してイベントソーシングを採用し、補償トランザクションを通じてビジネス不変量を強制しました。メリットには、パーティショナブルなイベントストリームによる固有の水平スケーラビリティ、詐欺分析に不可欠な不変の監査記録、および冪等性イベントの消費者を介した異種レガシーWMSとの自然な統合が含まれます。主な欠点は、不変データパターンに不慣れな開発者にとっての急な学習曲線と、新しい読み取りモデルのプロジェクションのためのイベントスキーマの進化と再生戦略の管理の運用の複雑さです。
アーキテクチャ委員会は、フラッシュセールが本質的に即時の整合性よりも可用性とパーティション耐性を優先するため、イベントソーシングアプローチを選択しました。ビジネスロジックは、ハードデータベースロックではなく、5分のTTLで一時的なソフト予約を受け入れることができました。ロックの代替案とは異なり、この設計により、データセンター間のネットワーク分割時にもシステムが可用のままであり、倉庫の確認が遅延している場合でも、顧客は常に購入を試みることができました。さらに、不変のイベントログは、財務チームが第三者の物流提供者との不一致を調整するために必要な監査可能性を提供しました。
実装は、ローカル在庫集約管理にKafka Streams、SAPおよびカスタムWMSシステム全体のサガオーケストレーションにTemporal、およびクエリ最適化のために書き込み通過キャッシュを使用したRedisをデプロイしました。次回のサイバーマンデーイベントでは、プラットフォームは120,000件の同時チェックアウトを成功裏に処理し、p99待機時間は80ms未満で、過剰販売のインシデントはゼロとなり、前のモノリシックアーキテクチャでは衰退してしまったus-east-1のシミュレートされた地域的障害にもかかわらず99.99%の可用性を維持しました。
グローバルロックなしで複数のKafkaパーティションにわたる同時予約を処理する際に、どのようにファントム在庫を防ぎますか?
ファントム在庫は、同時コマンドが異なるパーティションから古い在庫レベルを読み取り、両方が実際の可用性を超える予約をコミットする場合に発生します。これをグローバルロックなしで防ぐためには、イベントストア内のバージョン番号を使用して楽観的同時制御を実装します。各在庫集約は単調カウンターを維持し、コマンドには期待されるバージョンを含め、バージョンが不一致の場合には追加を拒否してクライアントの再試行を強制します。さらに、SKUを特定のパーティションにハッシュ化してパーティションの親和性を確保し、集約ごとの単一ライターセマンティクスを維持し、完全にクロスパーティションの協調を排除します。
ローカルイベントストアがすでに在庫の減少をコミットした後に、レガシーWMSのSOAPエンドポイントがタイムアウトした場合の補償トランザクション戦略は何ですか?
このシナリオは部分的な障害を示し、ローカル状態が外部の現実と乖離しているため、サガパターンを使用して後方回復が必要です。WMSアダプターがタイムアウトに遭遇すると、サガオーケストレーターにタイムアウトイベントを公開し、元の在庫を利用可能プールに戻すためにStock_Releasedイベントを追加します。特に、元の減少イベントを削除することは決して行わず、代わりに補償イベントを追加してトランザクション試行の完全な時間的履歴と監査の記録を保持します。
再構築プロセス中に、顧客に不整合な在庫数をさらさずにイベントの再生と読み取りモデルの再構築をどのように処理しますか?
CQRS読み取りモデルを再構築するためにイベントを再生すると、プロジェクションが徐々に更新される間にクエリが実行されると、一時的に不正確な在庫レベルを提示するリスクがあります。この問題の解決策は、読み取りモデル用にブルー・グリーンデプロイメントを採用します: 既存のインスタンスがトラフィックを処理している間、オフセット0からイベントログを消費する影のプロジェクションを作成し、影が追いついたときにルーティングを原子的に切り替えます。加えて、Kafkaのログ圧縮と定期的なS3スナップショットを利用して再生時間を短縮し、新しいプロジェクションが再構築中の潜在的な不整合ウィンドウを最小限に抑えることを確保します。