まずは用語について説明させていただきますが、分散型取引に関する情報を見ているとよく目にする用語が「逆補償#」です。 ##。逆補償とは何ですか?
例を示します: 今、3 つのマイクロサービス A、B、C があるとします。ここで、A サービスで B サービスと C サービスをそれぞれ呼び出します。B と C が成功するか失敗するかを確認するには、同時に、分散トランザクションも必要になります。しかし、ローカル トランザクションに関するこれまでの理解によれば、B と C のローカル トランザクションの場合、サービス B のトランザクションが完了して送信された後、サービス C のトランザクションには例外が発生し、ロールバックする必要があります。ただし、B はすでにロールバックされています。ロールバックするにはどうすればよいですか? 今回話しているロールバックは、従来の意味での、MySQL REDO ログを介したロールバックのようなものではありません。SQL の更新と、その後の B サービスの変更によるロールバックです。データ復旧です。
これを逆補償と呼びます。 2. 基本概念のレビューSeata には 3 つの中心概念があります:
次の図を見てみましょう:
この図は、基本的にこれら 3 つの概念を明確に説明しています。 実際、この図を見なくても、分散トランザクションの実装原理はおそらく推測できます。まず、グローバル トランザクション コーディネーター (TC) が存在する必要があり、各ローカル トランザクション (RM) が実行を開始します。実行プロセスは、そのステータスをグローバル トランザクション コーディネーターに速やかに報告します。このグローバル トランザクション コーディネーターは、各ブランチ トランザクションの現在の実行ステータスを知っています。彼 (TC) は、すべてのローカル トランザクションが正常に実行されたことを確認すると、全員に一緒にコミットするように通知します。 ; 誰かがこのトランザクションの実行に失敗したことを発見すると、全員に一緒にロールバックするように通知します (もちろん、このロールバックは必ずしも真のロールバックではなく、逆補償です)。では、トランザクションはいつ開始され、いつ終了するのでしょうか?つまり、トランザクションの境界はどこにあるのでしょうか? Seata の分散トランザクションは、@GlobalTransactional アノテーションによって実装されます。つまり、このアノテーションはどこに追加する必要がありますか?このアノテーションを追加する場所は、実際にはトランザクション マネージャー TM です。
まず次の図をご覧ください:
# #この図には 3 つの概念が含まれています:
言うまでもなく、AP はアプリケーションそのものです。
RM は、トランザクションの参加者であるリソース マネージャーです。ほとんどの場合、データベースを指します。分散トランザクションには、複数のトランザクションが関与することがよくあります。 RM。
TM は、分散トランザクションを作成し、分散トランザクション内の各サブトランザクションの実行とステータスを調整するトランザクション マネージャーです。 RM 上で実行される特定の操作に適用されます。
2 段階提出の真実は非常に単純です。ソング兄弟は、2 段階提出について説明する簡単な例を挙げます:
たとえば、次の図:
#Business では、それぞれ Storage、Order、Account と呼んでいますが、この 3 つの操作は同時に成功するか失敗する必要があります。異なるサービスでは、最初にこれら 3 つのサービスの操作を個別に実行させ、3 つのサービスのトランザクションを個別に実行させることができます。これが 2 つのフェーズのうちの第 1 フェーズです。
実行の最初のフェーズが完了したら、3 つのサービスの一部が実行に失敗している可能性があるため、急いで送信しないでください。この時点で、3 つのサービスは最初のフェーズの実行結果を報告する必要があります。トランザクション コーディネーターがメッセージを受信した後、3 つのサービスの最初のフェーズが正常に実行された場合、3 つのトランザクションはそれぞれ送信するように通知されます。3 つのサービスのいずれかの実行が失敗した場合、3 つのトランザクションは送信されます。現時点では通知されます。個別にロールバックしてください。これはいわゆる 2 フェーズ コミットです。
要約: 2 フェーズ送信では、トランザクションは参加者 (上図の各特定サービスなど) とコーディネーターに分割されます。参加者は操作の成功または失敗をコーディネーターに通知します。 , その後、コーディネーターはすべての参加者の結果に基づいて操作の成功または失敗を決定します。フィードバック情報により、各参加者が操作を送信するか操作を中止するかが決定されます。ここでの参加者は RM として理解でき、コーディネーターはコーディネーターです。 TM として理解できます。
ただし、Seata のさまざまな分散トランザクション モードは、基本的に 2 フェーズの送信に基づいて進化しているため、まったく同じではありません。
AT モードは、完全に自動のトランザクション ロールバック モードです。
全体として、AT モードは 2 フェーズ コミット プロトコルを進化させたものです。
1 フェーズ: ビジネス データとロールバック ログ レコードが同じローカル トランザクションで送信されます。 , ローカルのロックと接続リソースを解放します。
第 2 フェーズは 2 つの状況に分かれています: 2.1 非同期で送信します。これは非常に早く完了します。 2.2 ロールバックは、1 段階のロールバック ログを通じて逆補償を実行します。
一般的なロジックは上記のとおりです。特定のケースを通じて AT モードがどのように機能するかを見てみましょう:
次のようなビジネス テーブル製品があると仮定します。次のとおりです:
次に、次の更新操作を実行します:
update product set name = 'GTS' where name = 'TXC';
手順は次のとおりです。次のとおりです:
第一段階:
SQL の解析: SQL タイプ (UPDATE)、テーブル (プロダクト)、条件 (ここで、name = 'TXC') およびその他の関連情報。
クエリ前のイメージ: 解析で得られた条件情報をもとにクエリ文を生成し、データを検索します(更新前のデータを検索します)。
上記の更新SQLを実行します。
ミラー後のクエリ: ミラー前の結果に基づいて、主キーを通じてデータを見つけます。
ロールバック ログの挿入: 前後のミラー データとビジネス SQL 関連の情報をロールバック ログ レコードに結合し、UNDO_LOG テーブルに挿入します。
送信する前に、ブランチを TC に登録します。製品テーブル内の主キー値が 1 に等しいレコードのグローバル ロックを適用します。
ローカル トランザクションの送信: ビジネス データの更新は、前の手順で生成された UNDO ログとともに送信されます。
ローカル トランザクションの送信結果を TC に報告します。
第 2 フェーズ:
第 2 フェーズは、コミットまたはロールバックの 2 つの状況に分かれています。
最初にロールバック手順を見てみましょう:
まず、TC からブランチ ロールバック リクエストを受信し、ローカル トランザクションを開始して、次の操作。
XID とブランチ ID を使用して、対応する UNDO LOG レコードを検索します (このレコードには、データ変更の前後の対応するイメージが保存されます)。
データ検証: UNDO LOG のポストイメージと現在のデータを比較します。差異がある場合は、データが現在のグローバル以外のアクションによって変更されたことを意味します。取引。この状況は、構成ポリシーに従って処理する必要があります。
前のイメージの関連情報と UNDO LOG のビジネス SQL に基づいてロールバック ステートメントを生成して実行します: update product set name = 'TXC' where id = 1
;
ローカル トランザクションをコミットします。そして、ローカルトランザクションの実行結果(ブランチトランザクションのロールバック結果)をTCに報告します。
送信手順を見てみましょう:
TC からブランチ送信リクエストを受け取り、そのリクエストを非同期タスクキューを作成し、成功した送信の結果をすぐに TC に返します。
非同期タスクフェーズでのブランチ送信リクエストは、対応する UNDO LOG レコードを非同期かつバッチで削除します。
これはほぼ同じステップです。概念は比較的明確です。レコードを更新する場合、システムはレコードの更新の前後にコンテンツの JSON を生成します。そして、それをアンドゥログテーブルに保存します。将来ロールバックしたい場合は、アンドゥログの記録に従ってデータを更新(逆補正)します。将来ロールバックしたくない場合は、データを削除してください。アンドゥログに記録されます。
プロセス全体で、開発者は追加の UNDO ログ テーブルを作成し、グローバル トランザクションを処理する必要がある箇所に @GlobalTransactional
アノテーションを追加するだけで済みます。
その他の送信、ロールバック、ロールバックはすべて完全に自動で行われるため、簡単に実行できます。そのため、プロジェクトで分散トランザクションを処理するために Seata を使用することを選択した場合でも、AT モードを使用する可能性は依然として非常に高くなります。
TCC (Try-confirm-Cancel) モードは、少しマニュアル感があり、2 段階ですが、AT とは異なります。見てください、プロセス。
公式サイトに TCC のフローチャートがありますので見てみましょう:
ご覧のとおり、TCC はこれも 2 つの段階に分かれています:
最初の段階は準備です。この段階では主に銀行振込などのリソースの検出と予約が行われます。この段階では、まずユーザーの資金が十分であるかどうかを確認します。足りなければそのまま捨てますが、異常であればまず冷凍して十分です。
第 2 段階はコミットまたはロールバックです。これは主に、各ブランチ トランザクションの最初の段階が完了するのを待ちます。すべての実行が完了すると、それぞれが独自の状況をレポートします。 TC と TC は統計を作成し、TC が各ブランチ トランザクションに例外がないと判断した場合は全員にまとめて送信するよう通知し、TC がブランチ トランザクションが異常であると判断した場合は全員にロールバックするよう通知します。
そして、あなたの友人も、上記のプロセスには準備、コミット、ロールバックという合計 3 つのメソッドが含まれていることを発見したかもしれません。これら 3 つのメソッドは完全にユーザー定義のメソッドです。自分たちで実装するので、最初から TCC は手動モードであると言いました。
AT と比較すると、TCC モードは実際には基盤となるデータベースのトランザクション サポートに依存していないことがわかりました。つまり、基盤となるデータベースがトランザクションをサポートしていなくても問題ありません。とにかく、準備を整えます。 、commit、rollbackの3つすべてのメソッドは開発者自身が記述したものなので、この3つのメソッドに対応する処理をスムーズにすればよいのです。
XA 仕様は、X/Open 組織によって定義された分散トランザクション処理 (DTP、分散トランザクション処理) 標準です。
XA 仕様では、グローバル トランザクション マネージャーとローカル リソース マネージャー間のインターフェイスについて説明します。 XA 仕様の目的は、複数のリソース (データベース、アプリケーション サーバー、メッセージ キューなど) に同じトランザクションでアクセスできるようにし、
ACIDプロパティがアプリケーション間で有効なままになるようにすることです。 XA 仕様では、2 フェーズ コミットを使用して、すべてのリソースが特定のトランザクションを同時にコミットまたはロールバックすることを保証します。
XA 仕様は 1990 年代初頭に提案されました。現在、ほとんどすべての主流データベースが XA 仕様のサポートを提供しています。
XA トランザクションは、2 フェーズ コミット プロトコルに基づいています。すべてのトランザクション参加者が準備作業 (第 1 フェーズ) を完了していることを確認するには、トランザクション コーディネーターが必要です。コーディネーターは、すべての参加者が準備ができているというメッセージを受信すると、すべてのトランザクションをコミットできることを通知します (フェーズ 2)。 MySQL は、コーディネーター (トランザクション マネージャー) ではなく、この XA トランザクションの参加者の役割を果たします。
MySQL の XA トランザクションは、内部 XA と外部 XA に分かれています。外部 XA は外部分散トランザクションに参加でき、アプリケーション層がコーディネーターとして介入する必要があります。内部 XA トランザクションは、Binlog をコーディネーターとして、同じインスタンスの下でクロスエンジン トランザクションに使用されます。たとえば、ストレージ エンジンがコミットすると、情報は分散内部 XA トランザクションであるバイナリ ログに書き込まれます。ただし、バイナリ ログの参加者が MySQL 自体である点が異なります。 MySQL は、コーディネーターではなく、XA トランザクションの参加者の役割を果たします。
言い換えれば、MySQL は XA 仕様を通じて分散トランザクションを自然に実装できますが、必要なのは一部の外部アプリケーションのサポートのみです。 Seata での XA モードの使用プロセスを見てみましょう。まずは公式の写真を見てみましょう:
ご覧のとおり、これも 2 段階です。 submit :
フェーズ 1: ビジネス SQL 操作は XA ブランチで実行されます。XA ブランチが完了した後、XA prepare が実行され、RM のサポートによって永続性が保証されます。 XA プロトコル (つまり、その後の事故によってロールバックが不可能になることはありません)。
緑のプロセスは通常のプロセス、2 番目のセットは例外のプロセスです。その後の実行プロセスは次のようになります。例外が発生した後にロールバックされるプロセスです。ロールバックも一種の逆補償です。
以上がJava Spring Bootの分散トランザクションの問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。