大きな問題は、Webサービスへの重複した更新が重要かどうか、そしてそれらが検出できるかどうかです。重複を検出できる場合(通常は一意のトランザクション番号を使用)、または重複が問題にならない場合は、信頼性の高い2フェーズコミットスタイルのアプローチを構築できます。
Webサービスへの重複トランザクションを検出できず、更新がべき等でない場合は、運が悪いことになります。
これが基本的なアルゴリズムです。
begin transaction;
do local work;
save information for external call;
set an appropriate time for next attempt;
mark external call as not performed;
commit work;
begin transaction;
make external call;
if successful
mark external call as performed (or delete the record)
else
set the time for the next attempt
commit;
次に、通常のタスク、スレッド、または次のようなことを行うものが必要です。
for each record where the time for the next attempt <= now
begin work;
if the remote service has not performed this transaction
make the remote call;
if successful
mark as done;
else if too many attempts
mark the transaction as permanently failed;
alert operator;
else
set the time for the next attempt;
endif
else
mark as done;
endif
commit;
endfor
このアプローチは、すべての障害状態を確実に処理し、両方の作業が最終的に確実に行われるようにします。
基本的な失敗:
最初のコミットが完了する前の失敗:すべてがロールバックします。
最初のコミット後、Webサービスが完了する前の障害(これには、Webサービス自体の一時的な障害が含まれます):リモートWebサービストランザクションは、回復タスクによって再生されます。
Webサービスが完了した後、2番目のコミットが完了する前の障害:重複したWebサービス・トランザクションがリカバリー・タスクによって検出され、ローカル・レコードがデキューされます。
リカバリタスクの失敗:基本的に、2番目のトランザクションの失敗と同じです。
その他の注意事項:
段階的なバックオフアプローチは、障害に対して役立ちます。サービスで一時的な障害が発生した場合は、再試行を遅くします。
外部サービスに注文要件がある場合は、追加の構造が必要になる場合があります。
リカバリタスクの実装方法によっては、Webサービスの呼び出しをそのタスクに任せて、メインのアプリケーションフローに2番目のトランザクションを含めないようにすることができます。
追加要件への対応:「2つの部分のトランザクションは一緒に実行する必要があります。テーブルを同期するためにcronジョブを実行することは望ましくありません」
私がこの要件を読んだのは、「2つのシステムが失敗することは決してない」ということです。
一方または両方のシステムに障害が発生した場合、断片を拾い上げて調整するための何かが必要です。本格的なTPモニターを使用してトランザクションの調整を行うことも、特定のケースを処理する私の例のような単純なモニターを作成することもできます。いずれにせよ、障害状態の後で物事を正しく解決できるように、何が起こっていたかを追跡する何かがあります。
物事が常に一緒に発生することが本当に必要な場合(およびトランザクションメッセージキューまたは2フェーズコミットアプローチが機能しない場合)、両方のシステムのデータを同じデータベース(別名「リソースマネージャー」)に保存することをお勧めします。 )および単一のリソースマネージャートランザクションを持ちます。
複数のトランザクション間で2つの別個のシステムを一貫させるという要件を満たし、障害後にその後の調整を必要としないこの問題の解決策を入手した場合は、それを作成して、VLDBジャーナル、ACM TODS、またはIEEETKDEに公開する必要があります。 。