もちろん、TCC トランザクション フレームワークでは、分散トランザクションの管理を解決する必要があります。 TCC トランザクション メカニズムの概要については、「TCC トランザクション メカニズムの概要」を参照してください。 TCC トランザクション モデルは単純に聞こえますが、TCC に基づく一般的な分散トランザクション フレームワークを実装するのは、見た目よりもはるかに複雑です。これは、確認/キャンセル サービスへの単純な呼び出しではありません。 この記事では、Spring コンテナを例に、一般的な TCC 分散トランザクション フレームワークを実装する際に注意する必要があるいくつかの問題を分析します。 1. TCCグローバルトランザクションはRMローカルトランザクションに基づいて実装する必要がある TCC サービスは、Try/Confirm/Cancel サービスで構成されています。 Try/Confirm/Cancel サービスが実行されると、データにアクセスするためにリソース マネージャー (RM) がアクセスされます。 これらのアクセス操作は、変更されたデータがコミットまたはロールバックされるように、RM ローカル トランザクションに参加する必要があります。 これは理解するのが難しくありません。次のシナリオを考えてみましょう。 図のサービス B は RM ローカル トランザクションに基づいていないと仮定します (RDBS を例にとると、自動コミットを true に設定することでシミュレートできます)。 [B:Try] 操作が途中で失敗し、TCC トランザクション フレームワークがグローバル トランザクションをロールバックすることを決定すると、[B:Cancel] は [B:Try] 内のどの操作が DB に書き込まれ、どの操作が DB に書き込まれなかったかを判断する必要があります。 [B:Try] ビジネスには 5 つのデータベース書き込み操作があり、[B:Cancel] ビジネスではこれらの 5 つの操作が有効かどうかを 1 つずつ判断し、有効な操作に対して逆の操作を実行する必要があるとします。 残念ながら、[B:Cancel] ビジネスにも n (0<=n<=5) の逆書き込み操作があるため、[B:Cancel] も途中で失敗すると、後続の [B:Cancel] 実行タスクはさらに困難になります。 最初の [B:Cancel] 操作と比較して、後続の [B:Cancel] 操作では、前の [B:Cancel] 操作によるデータベースへの n (0<=n<=5) 回の書き込みのうちどれが実行され、どれが実行されなかったかを判断する必要もあります。 これにはべき等性の問題が関係しており、べき等性を確保するには追加のデータベース書き込み操作が必要になる可能性が高く、RM ローカル トランザクションがサポートされていないため、同様の問題が発生します。 。 。 RM ローカル トランザクションに基づいていない場合、TCC トランザクション フレームワークは TCC グローバル トランザクションを効果的に管理できないと考えられます。 対照的に、RM ローカル トランザクションに基づく TCC トランザクションの場合、この状況は簡単に処理できます。 [B:Try] 操作が途中で失敗した場合、TCC トランザクション フレームワークは、参加している RM ローカル トランザクションを直接ロールバックできます。 TCC トランザクション フレームワークがその後グローバル トランザクションをロールバックすることを決定した場合、[B:Try] 操作に関係する RM ローカル トランザクションがロールバックされたことがわかっている場合は、[B:Cancel] 操作を実行する必要はありません。 つまり、RM ローカルトランザクションに基づいて TCC トランザクションフレームワークを実装すると、TCC サービスのキャンセル業務は実行されるか実行されないかのいずれかとなり、部分的な実行状況を考慮する必要がなくなります。 2. TCCトランザクションフレームワークはSpringコンテナのTransactionManagerを引き継ぐ必要がある RM ローカル トランザクションに基づく TCC トランザクション フレームワークでは、各 Try/Confirm/Cancel ビジネスをアトミック サービスとして扱うことができます。つまり、RM ローカル トランザクションがコミットされると、RM ローカル トランザクションに参加しているすべての Try/Confirm/Cancel ビジネス操作が有効になります。それ以外の場合は、いずれも有効になりません。 各 RM ローカル トランザクションのステータスと、それらと Try/Confirm/Cancel ビジネス メソッド間の対応する関係を理解することにより、TCC トランザクション フレームワークは TCC グローバル トランザクションを効果的に構築できます。 RM 上の TCC サービスの Try/Confirm/Cancel ビジネス メソッドのデータ アクセス操作が実行され、Spring コンテナの PlatformTransactionManager によって RM ローカル トランザクションがコミット/ロールバックされます。 TCC トランザクション フレームワークが RM ローカル トランザクションのステータスを把握する必要がある場合、Spring トランザクション マネージャー機能を引き継ぐことによってのみそれを行うことができます。 2.1. TCC トランザクション フレームワークが RM ローカル トランザクションのステータスを理解する必要があるのはなぜですか? まず、TCC メカニズムの定義によれば、TCC トランザクションは、キャンセル ビジネスを実行することによってロールバック効果を実現します。注意深く分析すると、これは事実を暗示していることがわかります。つまり、有効な Try ビジネス オペレーションのみが、対応する Cancel ビジネス オペレーションの実行を必要とするということです。 つまり、Try ビジネス オペレーションが参加する RM ローカル トランザクションがコミットされた場合にのみ、後続の TCC グローバル トランザクションがロールバックされるときに、対応する Cancel ビジネス オペレーションを実行する必要があります。 そうでない場合、Try ビジネス操作に関係する RM ローカル トランザクションがロールバックされると、後続の TCC グローバル トランザクションがロールバックされたときに Cancel ビジネスを実行できません。このとき、やみくもにキャンセル業務を実行すると、データの不整合が発生します。 第二に、確認/キャンセル業務操作が有効であることが保証されなければなりません。確認/キャンセルのビジネス操作には RM データ アクセス操作も含まれており、それらが参加する RM ローカル トランザクションもコミットされる必要があります。 TCC トランザクション フレームワークは、TCC グローバル トランザクションを完了としてマークする前に、確認/キャンセル ビジネス操作に関係するすべての RM ローカル トランザクションが正常にコミットされたことを確実に認識する必要があります。 TCC トランザクション フレームワークが RM ローカル トランザクションに参加する確認/キャンセル ビジネスのステータスを誤って判断すると、グローバル トランザクションの不整合が発生します。 最後に、TCC グローバル TCC トランザクション フレームワークは、未完了の TCC トランザクションのコミット/ロールバック操作を再試行する必要があります。再試行時には、各 TCC サービスの確認/キャンセル業務操作が再度呼び出されます。 サービスの確認/キャンセル サービスが以前に有効になっていた場合 (そのサービスが参加している RM ローカル トランザクションがコミットされている場合)、再試行中に再度呼び出さないでください。そうしないと、Confirm/Cancel サービスが複数回呼び出された場合、「サービスのべき等性」の問題が発生します。 2.2. TCC サービスの Try/Confirm/Cancel ビジネス メソッドの実行をインターセプトします。例外情報に基づいて、RM ローカル トランザクションがコミット/ロールバックされたかどうかを知ることはできますか? 基本的に難しいのですが、なぜそう言うのですか? まず、トランザクションは複数の (ローカル/リモート) サービス間でトランザクション コンテキストを伝播できます。ビジネス メソッド (Try/Confirm/Cancel) が完了しても、必ずしも現在のトランザクションのコミット/ロールバック操作がトリガーされるわけではありません。 たとえば、トランザクション コンテキストが伝播されたビジネス メソッドの実行が開始されると、コンテナーはそのビジネス メソッドに対して新しいトランザクションを作成しません。代わりに、呼び出し元が参加するトランザクションは、同じトランザクション内で 2 つの操作を実行します。同様に、コンテナが実行されると、コンテナは参加しているトランザクションをコミット/ロールバックしません。 したがって、ビジネス方法に対するこのような例外は、それが効果的であるかどうかを反映するものではありません。 Spring の TransactionManager を引き継がなければ、トランザクションがいつ作成されたか、またはいつコミット/ロールバックされたかを知ることはできません。 2 番目に、ビジネス メソッドには複数の RM ローカル トランザクションが含まれる場合があります。 たとえば、A(REQUIRED)->B(REQUIRES_NEW)->C(REQUIRED) です。この場合、サービス A が参加している RM ローカル トランザクションがコミットされると、サービス B と C が参加している RM ローカル トランザクションがロールバックされる可能性があります。 3 番目に、ビジネス メソッドが例外をスローしたからといって、それが参加しているトランザクションがロールバックされるわけではありません。 Spring コンテナの宣言型トランザクションでは、システム例外 (通常はチェックされない例外、デフォルトのトランザクション完了方向はロールバック) とアプリケーション例外 (通常はチェックされる例外、デフォルトのトランザクション完了方向はコミット) の 2 種類の例外が定義され、トランザクション完了方向が異なります。 2 つのトランザクション完了方向は、rollbackFor/noRollbackFor などの @Transactional 構成を通じて明示的に指定できます。 4 番目に、Spring コンテナは、トランザクションの完了方向を明示的に制御するための setRollbackOnly の使用もサポートしています。 最後に、ビジネスメソッドを自らインターセプトするインターセプターと、Spring のトランザクション処理のインターセプターとの間には、実行順序やインターセプト範囲などの問題が生じます。 たとえば、自己インターセプターが最初に実行されると、ビジネス メソッドは実行されますが、それが参加する RM ローカル トランザクションはコミット/ロールバックされません。 TCC トランザクション フレームワークは、トランザクションのコミット/ロールバックを担当する TransactionManager として位置付ける必要があります。 トランザクションをコミットするかロールバックするかは、Spring コンテナによって決定されます。 Spring はトランザクションをコミットすることを決定すると、コミット操作を完了するために TransactionManager を呼び出します。 Spring はトランザクションをロールバックすることを決定すると、TransactionManager を呼び出してロールバック操作を完了します。 TCC トランザクション フレームワークは、Spring コンテナの TransactionManager を引き継ぐことで、Spring のトランザクション指示を明確に取得し、Spring コンテナ内の各サービスの RM ローカル トランザクションを管理できます。 それ以外の場合、自己インターセプト メカニズムが使用されると、ビジネス システムには、TCC トランザクション処理と RM ローカル トランザクション処理という 2 セットのトランザクション処理ロジックが存在することになります。 2 セットのトランザクション処理ロジックは相互に通信せず、独立して動作します。 この場合、TCC のグローバル取引を調整することは基本的に夢物語です。分散トランザクションは言うまでもなく、ローカル トランザクションも管理できません。 3. TCCトランザクションフレームワークには障害回復メカニズムが必要です TCC トランザクション フレームワークは、障害回復の保証がない場合は分散トランザクション フレームワークとは見なされません。 分散トランザクション管理フレームワークの役割は、グローバル トランザクションのコミット/ロールバック命令を発行することではなく、グローバル トランザクションのコミット/ロールバック プロセスを管理することです。 複数の RM リソースと複数のノードのブランチ トランザクションを調整して、グローバル トランザクションの完了の方向に各自のブランチ トランザクションが完了するようにする必要があります。 これは簡単なことではありません。実際のアプリケーションでは、さまざまな障害が発生し、その多くがトランザクションの中断を引き起こし、グローバル トランザクションの統一された送信/ロールバックの目標を達成できなくなり、「一部のブランチ トランザクションが送信されたが、他のブランチ トランザクションがロールバックされた」という状況が発生することもあります。 一般的な障害には、ビジネス システム サーバーのクラッシュ、再起動、データベース サーバーのクラッシュ、再起動、ネットワーク障害、停電などがあります。これらの障害は、個別に発生する場合もあれば、同時に発生する場合もあります。 分散トランザクション フレームワークとして、対応する障害回復メカニズムが必要です。こうした失敗の影響を無視するのは無責任です。 完全な分散トランザクション フレームワークは、最も理想的な環境下でのみこの保証を提供できるのではなく、最も厳しい条件下でもグローバル トランザクションの一貫性を確保する必要があります。一歩引いて考えると、いわゆる「理想的な環境」があれば、分散トランザクションを使用する必要はありません。 TCC トランザクション フレームワークが障害回復をサポートするには、対応するトランザクション ログを記録する必要があります。トランザクション ログは、さまざまなトランザクション データを記録する、障害回復の基礎および前提条件です。 TCC トランザクション フレームワークが障害回復を実行すると、トランザクション ログのデータに基づいて中断されたトランザクションを正しい状態に復元し、これに基づいて以前に完了していなかったコミット/ロールバック操作の実行を継続できます。 WeChat のパブリック アカウント「Java Technology Stack」をフォローし、バックグラウンドで「Architecture」と返信すると、私がまとめた N 個のアーキテクチャ チュートリアルが入手できます。これらはすべて実用的なものです。 4. TCCトランザクションフレームワークは、確認/キャンセルサービスに対して冪等性を保証する必要がある 一般的に、サービスのべき等性とは、同じサービスへの複数 (n>1) のリクエストと単一 (n=1) のリクエストが同じ副作用を持つことを意味すると考えられています。 TCC トランザクション モデルでは、さまざまな理由により、確認/キャンセル ビジネスが繰り返し呼び出される場合があります。 たとえば、グローバル トランザクションがコミットまたはロールバックされると、各 TCC サービスの確認/キャンセル ビジネス ロジックが呼び出されます。これらの確認/キャンセル操作を実行すると、ネットワークの中断などの障害が発生し、グローバル トランザクションが完了しない可能性があります。 したがって、障害回復メカニズムは、これらの未完了のグローバル トランザクションを後で再送信/ロールバックし、グローバル トランザクションに参加している各 TCC サービスの確認/キャンセル ビジネス ロジックを再度呼び出します。 Confirm/Cancel サービスは複数回呼び出される可能性があるため、その冪等性を保証する必要があります。 では、TCC トランザクション フレームワークは冪等性保護を提供するべきでしょうか?それとも、ビジネス システム自体が冪等性を保証する必要がありますか? 個人的には、TCC トランザクション フレームワークは冪等性保護を提供する必要があると思います。この問題が少数のサービスでのみ発生する場合、ビジネス システムが原因である可能性があります。 しかし、これは公的な問題です。すべての TCC サービスの確認/キャンセル業務に冪等性の問題があることは間違いありません。 TCC が扱う公共の問題は、TCC 取引フレームワークによって解決されるべきである。 さらに、ビジネス システムが冪等性に責任を持つ場合に考慮する必要がある問題を考慮すると、これがビジネス システムの複雑さを間違いなく増大させることがわかります。 5. TCCトランザクションフレームワークは、トランザクションをロールバックするためにキャンセルサービスに盲目的に依存することはできません。 前述のように、TCC トランザクションがキャンセル トランザクションを使用して Try トランザクションをロールバックするメカニズムは、Try 操作が有効になったという事実を暗示しています。 つまり、Try 操作に関係する RM ローカル トランザクションがコミットされた場合にのみ、その Cancel 操作を実行してロールバックする必要があります。実行されていない Try ビジネス、または実行されたが RM ローカル トランザクションがロールバックされた Try ビジネスは、Cancel ビジネスを実行してもロールバックできません。 したがって、TCC トランザクション フレームワークがグローバル トランザクションをロールバックする場合、TCC サービスの Try ビジネスの実行ステータスに基づいて適切な処理メカニズムを選択する必要があります。キャンセル サービスを盲目的に実行することはできません。そうしないと、データの不整合が発生します。 TCC サービスの Try 操作が有効かどうかは、TCC トランザクション フレームワークが認識する必要があります。これは、Try サービスが参加する RM トランザクションも、TCC トランザクション フレームワークによってコミット/ロールバックされるためです (TCC トランザクション フレームワークが Spring のトランザクション マネージャーを引き継ぐと仮定)。推奨事項: 分散トランザクションがわかりませんか?一気に説明しちゃいますよ。 したがって、TCC トランザクションがロールバックされると、TCC トランザクション フレームワークは次の処理戦略を検討できます。
要約すると、TCC トランザクション フレームワークは次のことを保証する必要があります。
6. キャンセル業務はトライ業務と並行して実行されるか、またはトライ操作の前に完了する これは、TCC トランザクション メカニズムに特有の驚くべき罠であると考えるべきです。 一般的に、特定の TCC サービスの Try 操作は、その Confirm/Cancel 操作の前に実行する必要があります。 Try 操作が実行されると、Spring コンテナは、Try 操作の実行ステータスに基づいて、TCC トランザクション フレームワークにグローバル トランザクションをコミット/ロールバックするように指示します。次に、TCC トランザクション フレームワークは、各 TCC サービスの確認/キャンセル操作を 1 つずつ呼び出します。 ただし、タイムアウト、ネットワーク障害、サーバーの再起動、その他の障害により、この順序が乱れる可能性があります。例えば: 上図では、[B:Try] 操作の実行中にネットワークが切断された場合、[A:Try] は RPC リモート呼び出し例外を受信します。 A は例外を処理せず、グローバル トランザクションがロールバックされます。 TCC トランザクション フレームワークは [B:Cancel] を呼び出し、この時点で A と B 間のネットワークが復元されました。 [B:Try] 操作に時間がかかる場合 (ネットワーク混雑/データベース操作混雑)、[B:Try] と [B:Cancel] は並列処理され、[B:Cancel] が先に完了します。 この場合、[B:Cancel] が実行されたときに [B:Try] はまだ有効になっていない (その RM ローカル トランザクションはまだコミットされていない) ため、[B:Cancel] は実行できないか、少なくとも有効になりません (実行された場合、その RM ローカル トランザクションはロールバックされる必要があります)。 ただし、[B:Cancel] が処理された後 (実行がスキップされるか、実行後に RM ローカル トランザクションがロールバックされる)、[B:Try] 操作が完了し、再度有効になります (RM ローカル トランザクションが正常にコミットされます)。つまり、[B:Cancel] は提供されているものの、[B:Try] をロールバックする役割を果たしておらず、データの不整合が発生しています。 したがって、この場合の TCC フレームワークでは次のことが必要です。
もちろん、TCC トランザクション フレームワークは、[B:Cancel] の処理をブロックすることを選択することもできます。[B:Try] が実行された後、実行ステータスに基づいて [B:Cancel] を実行する必要があるかどうかを決定します。 ただし、この処理方法では待機が必要になるため、処理効率は若干低くなります。 確認業務でも同様の状況が発生しますが、確認業務で発生する処理ロジックはキャンセル業務で発生する処理ロジックとは異なります。 TCC フレームワークでは、次の点を保証する必要があります。
7. TCC サービスの再利用性は比較的低いですか? TCC トランザクション メカニズムの定義では、サービスが 3 つのビジネス実装 (試行ビジネス、確認ビジネス、キャンセル ビジネス) を提供する必要があることが定められています。 TCC サービスの再利用性が低いと考える人もいるかもしれません。言い換えれば、再利用のために Try/Confirm/Cancel のビジネス ロジックを個別に取り出した場合、その再利用性は確かに良くありません。 TCC サービスの一部として、Try/Confirm/Cancel ロジックを個別のコンポーネントとして再利用することはできません。 Try、Confirm、および Cancel の各サービスが一緒にコンポーネントを構成します。再利用する場合は、個別の Try/Confirm/Cancel サービスではなく、TCC サービス コンポーネント全体を再利用する必要があります。 8. TCC サービスでは 3 つのサービス インターフェイスを公開する必要がありますか? 不要。 TCC サービスは共通サービスと同じであり、1 つのインターフェース、つまり Try サービスのみを公開する必要があります。 確認/キャンセル ビジネス ロジックは、グローバル トランザクションのコミット/ロールバックの必要性があるためにのみ提供されます。したがって、確認/キャンセル ビジネスは、TCC トランザクション フレームワークによってのみ検出され、それを呼び出す他のビジネス サービスによって認識される必要はありません。 つまり、ビジネス システムの他のサービスが TCC サービスを呼び出す必要がある場合、それが TCC タイプのサービスであるかどうかを知る必要はありません。 なぜなら、他のビジネス サービスから呼び出すことができる TCC サービスは Try サービスのみであり、Confirm/Cancel サービスは他のビジネス サービスから直接呼び出すことができないからです。 IX. TCC サービス A の確認/キャンセル サービスは、依存する TCC サービス B の確認/キャンセル サービスを呼び出すことができますか? そんなことしないほうがいいですよ。 まず第一に、それは必要ありません。 TCC サービス A は TCC サービス B に依存しているため、[A:Try] はトランザクション コンテキストを [B:Try] に伝播し、TCC トランザクション フレームワークはそれぞれの Confirm/Cancel サービスを呼び出します。 次に、確認/キャンセル業務が他のサービスを呼び出すことが許可されている場合、新しい TCC グローバル トランザクションを再度開始することが可能です。この再帰的な動作は、混沌とした制御不能なグローバルトランザクション関係につながります。 TCC グローバル トランザクションは、Try 操作フェーズ中にトランザクション コンテキストを伝播しようとする必要があります。確認/キャンセル操作フェーズでは、それぞれの Try ビジネス操作の確認/補償操作を完了するだけで済みます。リモート呼び出しには適しておらず、トランザクション コンテキストを外部に伝播することはできません。 要約すると、この記事では、一般的な TCC 分散トランザクション管理フレームワークの実装は比較的複雑であると考えています。一般的な業務システムで TCC トランザクション メカニズムを使用する必要がある場合、独自に設計して実装することは推奨されません。 ここでは、オープンソースの TCC 分散トランザクション マネージャー ByteTCC をお勧めします https://github.com/liuyangming/ByteTCC ByteTCC は、Spring コンテナとシームレスに統合でき、Spring の宣言型トランザクション管理と互換性のある Try/Confirm/Cancel メカニズムに基づいて実装されています。 dubbo フレームワークと Spring Cloud のすぐに使用できるサポートを提供し、複数のデータ ソース、アプリケーション間、サーバー間などのさまざまな分散トランザクション シナリオのニーズを満たします。 |
<<: ファーウェイクラウドクンペンクラウドサービスが多様なコンピューティングパワーを開始し、企業のインテリジェントアップグレードを促進
>>: Kafka のこれらの原則を説明していただけますか?
5月中旬、起業家コミュニティの人々は、WJW.comがJD.comに盗作されたというニュースを聞いた...
この記事の目的は、現代のソフトウェア業界の重要なトピックであるクラウドネイティブ アプリケーションに...
ソフトウェアの依存関係は、効果的なコンポーネントベースのプログラミングの重要な部分です。同時に、ソフ...
COVID-19パンデミック後、モバイルゲームの収益の減少により、世界のモバイルアプリケーション全体...
dedistation.com は比較的新しい VPS プロバイダーです。私は以前、HostCat ...
社内ではいつでも、リーダーがチームスピリットを強調するのを耳にします。SEOでも同じです。今はもう一...
ウェブサイトの構築と運用は根気のいる仕事であり、ウェブマスターの皆さんは膨大な作業量であることを認識...
extravm は現在、米国南東部の自社マイアミ データ センターで VPS を 25% 割引で提供...
SEO を行っているウェブマスターにとって、外部リンクのクエリは常に頭痛の種でした。一般的に使用され...
ロングテールキーワードの設定は、ウェブマスターにとって常に頭痛の種でした。多くのウェブマスターは、メ...
[[381481]]この記事はWeChatの公開アカウント「Full-Stack Coder Po...
2012年の新メディア、WeChat!インターネット、特にモバイルインターネットを利用する人にとって...
カンボジア VPS には独自の利点があります。管理が非常に緩やかであるか、まったく存在しないため、ビ...
ほぼすべての SEO 担当者は、Web サイトの検索トラフィックのほとんどが、単一検索の少ないロング...
2011年6月に迅雷がSECに上場申請を提出し、10月に最終的に申請を取り下げてから、ほぼ1年が経過...