分散トランザクションとソリューションに関する簡単な説明 | JD Logistics Technology Team

背景1枚

分散トランザクションの概念を説明する前に、まずトランザクションに関連するいくつかの概念を確認しましょう。

1.1 トランザクションの基本概念

これはプログラムの実行単位であり、すべての操作が正常に実行されるか、すべての実行が失敗します。操作の半分だけが成功し、残りの半分は失敗します。たとえば、トランザクション コードが 2 つのデータベース更新操作を実行する場合、これら 2 つのデータベース操作は正常に実行されるか、ロールバックされます。

1.2 取引の基本的な特徴

トランザクションには、よく (ACID) と呼ばれる 4 つの非常に重要な特性があることがわかっています。

  • アトミック性: トランザクション内のすべての操作は完全に完了するか、未完了のいずれかであり、中間段階で終了することはありません。トランザクション実行中にエラーが発生した場合は、トランザクションが実行されなかったかのように、トランザクション開始前の状態に復元(ロールバック)されます。
  • 一貫性: データベースの整合性は、トランザクションの開始前と終了後に損なわれません。これは、書き込まれるデータが、データの精度や連結など、事前に設定されたすべてのルールに完全に準拠する必要があり、後続のデータベースが所定の作業を自発的に完了できることを意味します。
  • 分離: 複数の同時トランザクションがデータを同時に読み取り、書き込み、変更できるようにするデータベースの機能。分離により、複数のトランザクションが同時に実行される場合のクロス実行によるデータの不整合を防ぐことができます。トランザクション分離は、非コミット読み取り、コミット読み取り、反復読み取り、シリアル化可能など、さまざまなレベルに分かれています。
  • 耐久性: トランザクションが完了すると、データへの変更は永続的に保持され、システムに障害が発生しても失われることはありません。

2 分散トランザクション

実は、分散トランザクションの概念はデータベーストランザクションと本質的に同じであり、トランザクションである以上、トランザクションの基本特性(ACID)を満たす必要がありますが、分散トランザクションの表現はデータベーストランザクションとは大きく異なります。現地取引です。

ローカル トランザクションの時代では、データベースの複数のレコードを同時に操作する必要があり、これらの操作をトランザクションに含めることができる場合、データベースが提供するトランザクション メカニズムを通じてそれを実現できます。

マイクロサービス アーキテクチャの進歩により、ローカルの論理実行ユニットが複数の独立したマイクロサービスに分割され、これらのマイクロサービスはそれぞれ異なるデータベースやテーブルを操作します。

例えば、個別の輸送タスクを割り当てる場合、要件、計画、タスクを同時に生成し、問い合わせサービスや保険サービスを呼び出す必要があり、サービス例外が発生すると、トランザクション上の問題が発生します。現在のロジックは運用によって無効化できますが、将来の自動化後はどうなるでしょうか?

分散トランザクションは、マイクロサービス アーキテクチャ (すべての形式が分散システム) の異なるノード間のデータの一貫性の問題を解決するように設計されています。この一貫性の問題は、従来のトランザクションが解決する必要がある問題、つまり、リクエストが複数のマイクロサービス呼び出しチェーンにある場合、すべてのサービスのデータ処理が成功するかロールバックされるか、という問題を本質的に解決します。もちろん、分散トランザクションの問題の形式は従来のトランザクションとはまったく異なる場合がありますが、問題の本質は同じであり、それらはすべてデータの一貫性の問題を解決する必要があります。

分散トランザクションを実装するには多くの方法がありますが、最も代表的な方法は、Oracle Tuxedo システムによって提案されている XA 分散トランザクション プロトコルです。XA プロトコルには 2 フェーズ コミット (2PC) と 3 フェーズ コミット (3PC) の 2 つの実装方法がありますが、次にこれら 2 つの実装方法の原理をそれぞれ紹介します。

3 2 フェーズ提出 (2PC)

2 フェーズ コミットは 2PC (2 フェーズ コミット プロトコル) とも呼ばれ、2PC は非常に古典的な強力な一貫性のある集中型のアトミック コミット プロトコルです。ここで言う集中化とは、プロトコルに 2 つの役割があることを意味します。1 つは分散トランザクション コーディネーター (調整者) であり、N 人の参加者 (参加者) です。

3.1 2PC の動作原理

二段階提出とは、その名のとおり、第一段階の準備段階(投票段階)と第二段階の提出段階(実行段階)の二段階で提出します。

3.1.1 準備フェーズ

  1. 分散トランザクションのイニシエーターは、分散トランザクション コーディネーター (Coordinator、トランザクション管理 TransactionManager とも呼ばれます) にリクエストを送信します。
  2. コーディネーターは、準備と呼ばれるトランザクション前処理リクエストを参加者 A と参加者 B にそれぞれ送信します。一部のデータは「投票リクエスト」とも呼ばれます。
  3. 現時点では、これらの参加者ノードは通常、ローカル データベース トランザクションを開いてから、データベース ローカル トランザクションの実行を開始します。各データベース参加者はローカルでトランザクションを実行し、ローカルの Undo/Redo ログを書き込みます (Undo ログは、変更前のデータを記録します。データベースのロールバックに使用される、Redo ログ)変更されたデータを記録し、トランザクションのコミット後にデータ ファイルを書き込むために使用されます)が、実行完了後、データベースのローカル トランザクションはすぐには送信されず、最初にコーディネーターに対して「コミットの投票」が実行されます。処理結果をフィードバックして通知します。
  4. すべての参加者がコーディネーターに「投票コミット」フィードバックを送信すると、プロセスは第 2 段階に入ります。

3.1.2 コミットフェーズ

1) すべての参加者が成功を報告すると、コーディネーターはすべての参加者に「グローバル コミット確認通知 (global_commit)」を送信し、参加者は自身のローカル データベース トランザクションの送信を完了し、送信結果を返信します。ack" メッセージコーディネータ Coordinator に分散トランザクション処理の完了結果を返します。いずれかの参加者が失敗を返した場合、トランザクションはロールバックされます。

2) 参加者が「Vote_Abort」メッセージをコーディネーターにフィードバックすると、失敗メッセージが返されます。このとき、分散トランザクション コーディネーターは、すべての参加者に対してトランザクション ロールバック メッセージ ("global_rollback") を開始します。この時点で、各参加者はローカル トランザクションをロールバックし、リソースを解放し、コーディネーターに "ack" を送信します。メッセージを確認すると、コーディネーターは分散トランザクション処理の失敗結果を呼び出し元に返します。

以上が 2 フェーズ提出の基本的なプロセスですが、この 2 フェーズ提出プロトコルに従って、分散システムのデータ整合性の問題は解決できるのでしょうか?

3.2 2PCの問題点

実際、2PC は、2 段階の処理プロセスを通じてトランザクション コーディネーター (Coordinator) の役割を追加することによって、複数のサービスにわたる分散システムにおけるトランザクションのデータ整合性の問題を解決するだけです。

以下の点は、XA 2 フェーズ コミット プロトコルで発生する問題の一部です。

  • パフォーマンスの問題: 2PC のすべての参加ノードはトランザクションをブロックしているため、参加ノードで通信タイムアウトが発生すると、他の参加ノードは受動的にブロックされ、解放できないリソースを占有します。
  • コーディネーターの単一障害点の問題: コーディネーターへの依存度が高いため、コーディネーターに障害が発生すると、参加者は引き続きリソースがロックされた状態になり、トランザクションのコミット操作を完了できなくなります。コーディネーターが失敗した場合、コーディネーターは再選されますが、前コーディネーターの失敗により参加者がブロックされる問題は解決できません。
  • ネットワーク中断はスプリット ブレインにつながります。第 2 フェーズでは、コーディネーターが参加者にコミット コマンドを送信した後、この時点でネットワーク ジッターが発生すると、一部の参加者はコミット リクエストを受信して​​実行しますが、コミット リクエストを受信して​​いない他の参加者はコミット リクエストを受信して​​実行します。コミットリクエストはトランザクションコミットを実行できません。これにより、分散システム全体でデータの不整合が生じます。

4 3段階提出(3PC)

3PC とも呼ばれる 3 フェーズ送信では、2PC に基づいて CanCommit ステージが追加され、タイムアウト メカニズムが導入されます。トランザクション参加者がコーディネーターからのコミット要求の受信に失敗すると、ローカル コミットが自動的に実行され、コーディネーターの単一障害点の問題が比較的効果的に解決されます。

4.1 3PC の動作原理

4.1.1 CanCommit フェーズ

  1. コーディネーターは参加者に CanCommit を発行してトランザクション照会操作を実行し、参加者全員が「はい」と応答して初めて次の段階に進むことができます。(第 1 段階でテーブルのロックを開始する 2pc とは異なり、この段階ではテーブルはロックされません。3pc の第 1 段階では、個々の参加者がトランザクションをコミットする能力を持たないという前提でテーブルのロックを回避します。)簡単な用語 自分の状態の健康状態をチェックするだけです。
  2. いずれかの参加者が「いいえ」と応答した場合、分散トランザクション全体が中断され、コーディネーターはすべての参加者に「中止」リクエストを送信します。

4.1.2 プレコミットフェーズ

  1. フェーズ 1 で、すべての参加者が「はい」を返した場合、トランザクションの事前コミットのための PreCommit フェーズに入ります。このとき、分散トランザクション コーディネーターはすべての参加者に PreCommit リクエストを送信し、それを受信した参加者はトランザクション操作の実行を開始し、Undo および Redo 情報をトランザクション ログに記録します。参加者がトランザクション操作を完了すると (この時点ではコミットされていないトランザクションの状態にあります)、送信の準備ができていることを示すためにコーディネーターに「Ack」をフィードバックし、コーディネーターの次の指示を待っています。
  2. いずれかの参加者のフィードバックの結果が「いいえ」になるか、参加者ノードからのフィードバックを待っている間にコーディネーターがタイムアウトになります (2PC ではコーディネーターのみがタイムアウトになり、参加者用のタイムアウト メカニズムはありません)。分散トランザクション全体が中止され、コーディネーターはすべての参加者に「中止」リクエストを送信します。

4.1.3 DoCommitフェーズ

  1. フェーズ 2 では、参加者全員が PreCommit 送信を実行できる場合、コーディネーターが「PreCommit ステータス」→「コミット ステータス」に変わります。次に、すべての参加者に "doCommit" リクエストを送信します。コミット リクエストを受信した後、パーティシパントはトランザクションの送信操作を実行し、"Ack" メッセージをコーディネーターにフィードバックします。コーディネーターは、すべての参加者から Ack メッセージを受信した後、トランザクションを完了します。
  2. 同様に、参加者ノードが PreCommit フィードバックを完了できなかった場合、またはフィードバックがタイムアウトした場合、コーディネーターはすべての参加者ノードに中止要求を送信し、トランザクションを中断します。

2PC と比較して、3PC はコーディネータとパーティシパントの両方にタイムアウトを設定するため、パーティシパントがコーディネータ ノードと長時間通信できない(コーディネータがハングアップする)という問題が解決されます。タイムアウト メカニズムがあり、タイムアウト後にローカル コミットを自動的に実行してリソースを解放します。このメカニズムにより、トランザクション全体のブロック時間と範囲も短縮されます。
さらに、CanCommit、PreCommit、および DoCommit の 3 つのステージの設計により、2PC と比較して追加のバッファー ステージが設定され、最終的な送信ステージの前に各参加ノードのステータスの一貫性が保証されます。

3PC のデメリット:

3PC はブロッキングを除去しますが、参加者がプリコミット メッセージを受信した後、ネットワークの分断が発生すると、コーディネーターが位置するノードと参加者が正常に通信できなくなるという新たな問題も発生します。それでもトランザクションをコミットするため、必然的にデータの不整合が生じます。

5 補償事項(TCC)

TCC は、2PC や 3PC と同様、分散トランザクションの実装ソリューションにすぎません。

5.1 TCC 原則:

TCC(Try-confirm-Cancel)は補償取引とも呼ばれます。中心的な考え方は、「各操作に対して、対応する確認と補償 (取り消し操作) を登録する必要がある」というものです。それは 3 つの操作に分かれています。

  • 試行ステージ: 主にビジネス システムのテストと、在庫の凍結などのリソースの確保を行います。
  • 確認段階:業務の実行を確認する。
  • キャンセル段階:業務の実行をキャンセルします。

TCC トランザクションの処理フローは 2PC の 2 段階送信のフローと似ていますが、2PC は通常クロスデータベース DB レベルにあり、TCC は本質的にアプリケーション レベルの 2PC であり、ビジネス ロジックを通じて実装する必要があります。この分散トランザクション実装の利点は、アプリケーションがデータベース操作の粒度を定義できるため、ロックの競合を削減し、スループットを向上できることです。

欠点は、アプリケーションにとって非常に煩わしいことであり、ビジネス ロジックの各ブランチでは、try、confirm、cancel の 3 つの操作を実装する必要があります。さらに、その実装は比較的難しく、ネットワーク状態やシステム障害などのさまざまな障害理由に応じて、さまざまなロールバック戦略を実装する必要があります。一貫性の要件を満たすために、確認インターフェイスとキャンセル インターフェイスも冪等である必要があります。

TCC の具体的な回路図は次のとおりです。

5.2 注:

1. 業務運営は 2 つの段階で完了します。

TCC にアクセスする前は 1 ステップで業務が完了しますが、TCC にアクセスした後はリソースの確認と予約を 1 段階の Try オペレーションで行い、実際の操作は、ビジネス操作の実行が第 2 段階の確認操作で実行されます。TCC
サービスは、第 1 段階の Try 操作が成功した後、第 2 段階の確認操作が成功することを確認する必要があります。

2. 空のロールバックを許可します。

トランザクション コーディネーターが TCC サービスの 1 段階の Try オペレーションを呼び出すと、パケット損失によりネットワーク タイムアウトが発生することがあります。このとき、トランザクション コーディネーターは 2 段階のロールバックをトリガーし、TCC サービスの Cancel オペレーションを呼び出します
。 Try リクエストが作成されると、Cancel リクエストが受信されます。このシナリオは空のロールバックと呼ばれます。TCC サービスは、実装時に空のロールバックの実行を許可する必要があります。

3. アンチサスペンション制御;

トランザクション コーディネーターが TCC サービスの 1 段階の Try オペレーションを呼び出すと、ネットワークの輻輳によりタイムアウトが発生する場合があります。このとき、トランザクション コーディネーターは 2 段階のロールバックをトリガーし、TCC サービスの Cancel オペレーションを呼び出します。つまり、ネットワーク上の第 1 段階の Try パケットが TCC サービスによって受信され、第 1 段階の Try リクエストの前に第 2 段階の Cancel リクエストが実行され、輻輳が発生します。TCC サービスを実装する場合、ユーザーは空のロールバックを許可する必要があります
。 Try リクエストの次のフェーズが始まります。

4. 冪等制御:

ネットワーク データ パケットの再送信や異常トランザクションの補償実行など、TCC サービスの Try、confirm、または Cancel 操作が繰り返し実行されるため、TCC サービスを実装する際には、冪等制御、つまり、冪等制御を考慮する必要があります。 Try、confirm、Cancel の実行 1 回実行しても複数回実行してもビジネス結果は同じです。

5. ビジネスデータの可視性制御。

TCC サービスの第 1 段階の Try オペレーションでリソースが予約されますが、第 2 段階のオペレーションが実行される前に、他のトランザクションが予約されたリソース データを読み込む必要がある場合、中間状態のビジネス データをユーザーにどのように表示するかがビジネスで必要になります。実装するときは明確に考えてください。通常の設計原則は、「過剰に表示したり間違って表示したりするよりも、まったく表示しないか、表示しないか少ない方が良い」です。

6. ビジネスデータの同時アクセス制御。

TCC サービスの第 1 段階の Try 操作でリソースが予約された後、予約されたリソースは第 2 段階の操作が実行されるまで解放されません。この時点で他の分散トランザクションがこれらのビジネス リソースを変更すると、分散トランザクションの同時実行性の問題が発生します。 TCC サービスを実装する
場合、ユーザーはビジネス データの同時実行性の制御を考慮し、分散トランザクションの同時実行性を最大化するために論理ロックの粒度を最小限に抑えるように努める必要があります。

6 微笑み

Hmily (How much I love you)
高性能分散トランザクション TCC オープンソース フレームワーク。Java言語(JDK1.8)をベースに開発されており、dubbo、springcloud、motanなどの分散トランザクション用RPCフレームワークをサポートしています。

フレームのプロパティ

  • ネストされたトランザクションをサポートします (ネストされたトランザクションのサポート)。
  • トランザクション ログの非同期読み取りおよび書き込みにディスラプター フレームワークを使用しても、RPC フレームワークとパフォーマンスに違いはありません。
  • SpringBoot-starter プロジェクトの起動をサポートしており、使いやすいです。
  • RPC フレームワークは、dubbo、motan、springcloud をサポートします。
  • ローカル トランザクション ストレージのサポート: redis、mongodb、zookeeper、file、mysql。
  • トランザクション ログのシリアル化のサポート: java、hessian、kryo、protostuff。
  • Aspect AOP アスペクトのアイデアを採用して Spring とシームレスに統合し、クラスタリングを自然にサポートします。
  • これには、古典的な分散トランザクション シナリオのデモ プロジェクトと、迅速な体験のための swagger-ui ビジュアル インターフェイスが組み込まれています。

6.1 Hmilyの原理とフローチャート

回路図:

フローチャート:

7 参考文献

  • https://dromara.org/website/zh-cn/docs/hmily/index.html
  • https://houbb.github.io/2018/10/30/hmily
  • https://developer.aliyun.com/article/609854
  • https://blog.csdn.net/bjweimengshu/article/details/86698036
  • https://blog.csdn.net/u014296316/article/details/90185589

著者: JD Logistics Song Le

出典:JD Cloud Developer Community Ziyuanqishuo Tech 転載の際は出典を明記してください

 

Lei Jun: Xiaomi の新しいオペレーティング システム ThePaper OS の正式版がパッケージ化されました。Gome App の抽選ページのポップアップ ウィンドウは創設者を侮辱しています。Ubuntu 23.10 が正式にリリースされました。金曜日を利用してアップグレードするのもいいでしょう! Ubuntu 23.10 リリース エピソード: ヘイトスピーチが含まれていたため、ISO イメージが緊急に「リコール」されました 23 歳の博士課程の学生が Firefox で 22 年間続いた「ゴーストバグ」を修正しました RustDesk リモート デスクトップ 1.2.3 がリリースされましたWayland を強化して TiDB 7.4 をサポート リリース: MySQL 8.0 と正式互換. Logitech USB レシーバーを取り外した後、Linux カーネルがクラッシュしました. マスターは Scratch を使用して RISC-V シミュレータをこすり、Linux カーネルを正常に実行しました. JetBrains が Writerside ツールを開始しました技術文書の作成に。
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10119729