分散トランザクションの面接での質問

1. 事業紹介

トランザクションとは、データベース内の特定のデータ項目を操作するプログラムの実行単位です。

トランザクションには、原子性、一貫性、分離性、耐久性という 4 つの属性が必要です。これら 4 つのプロパティは、多くの場合、ACID プロパティと呼ばれます。

1.1. 用語集

  • トランザクション: トランザクションは一連の操作で構成される信頼性の高い独立した作業単位であり、アトミック性、一貫性、分離性、耐久性といった ACID 特性を備えています。
  • ローカル トランザクション: トランザクションがリソース マネージャーによってローカルに管理される場合、そのトランザクションはローカル トランザクションと呼ばれます。ローカル トランザクションの利点は、厳密な ACID 特性をサポートし、効率的で信頼性が高く、リソース マネージャー内でのみ状態を維持できること、およびアプリケーション プログラミング モデルがシンプルであることです。ただし、ローカル トランザクションには分散トランザクションの処理能力がなく、分離の最小単位はリソース マネージャーによって制限されます。
  • グローバル トランザクション: トランザクションがグローバル トランザクション マネージャーによってグローバルに管理される場合、そのトランザクションはグローバル トランザクションになります。トランザクション マネージャーは、グローバル トランザクションのステータスと参加リソースの管理を担当し、リソースの一貫したコミットとロールバックを調整します。
  • TX プロトコル: アプリケーションまたはアプリケーション サーバーとトランザクション マネージャー間のインターフェイス。
  • XA プロトコル: グローバル トランザクション マネージャーとリソース マネージャー間のインターフェイス。XA は、X/Open 組織によって提案された分散トランザクション仕様です。この仕様は主に、グローバル トランザクション マネージャーとローカル リソース マネージャー間のインターフェイスを定義します。すべての主流データベース製品は XA インターフェイスを実装しています。XA インターフェイスは、トランザクション マネージャーと複数のリソース マネージャー間の通信ブリッジとして機能する双方向のシステム インターフェイスです。XA が必要な理由は、理論的に言えば、分散システムでは 2 台のマシンが一貫した状態を達成できないため、調整のための単一ポイントが導入されるためです。グローバル トランザクション マネージャーによって管理および調整されるトランザクションは、複数のリソースおよびプロセスにまたがることができます。グローバル トランザクション マネージャーは通常、XA 2 フェーズ プロトコルを使用してデータベースと対話します。
  • AP: アプリケーションプログラム。DTP (Data Tools Platform) を使用したプログラムとして理解できます。
  • RM: DBMS またはメッセージ サーバー管理システムであるリソース マネージャー。アプリケーションはリソース マネージャーを通じてリソースを制御します。リソースは XA によって定義されたインターフェイスを実装する必要があります。リソース マネージャーは、実際のリソースの制御と管理を担当します。
  • TM: トランザクション マネージャー。トランザクションの調整と管理、AP プログラミング インターフェイスの提供、リソース マネージャーの管理を担当します。トランザクション マネージャーは、グローバル トランザクションを制御し、トランザクションのライフサイクルを管理し、リソースを調整します。
  • 2 フェーズ コミット プロトコル: グローバル トランザクションで複数のリソースを調整するための XA のメカニズム。一貫性の問題を解決するために、TM と RM の間で 2 段階の送信ソリューションが採用されています。2 ノードのコミットでは、コーディネーター (TM) がすべての参加者 (RM) ノードの操作の結果を保持し、これらのノードに最終コミットが必要かどうかを指示する必要があります。2 フェーズ コミットの制限は、プロトコルのコスト、準備フェーズの永続的なコスト、グローバル トランザクション状態の永続的なコスト、および多くの潜在的な障害ポイントによって引き起こされる脆弱性にあります。準備後およびコミット前の失敗は原因となります。一連の分離と回復の問題。
  • BASE 理論: BA は基本的なビジネス可用性を指し、パーティション障害をサポートします。S は柔軟な状態を表し、短期間での非同期が可能です。E は最終的な整合性を表します。データは最終的には一貫していますが、リアルタイムでは一貫性がありません。原子性と耐久性は基本的に保証されなければならず、可用性、パフォーマンス、サービス低下のニーズを満たすためには、一貫性と分離性の要件のみを軽減する必要があります。
  • CAP 定理: 共有データ システムの場合、最大 2 つの CAP を同時に所有でき、任意の 2 つには独自の適切なシナリオがあります。実際のビジネス システムは、通常、ACID と CAP の混合です。分散システムで最も重要なことは、高度に抽象的かつ絶対的なシステム特性を追求することではなく、ビジネス ニーズを満たすことです。C は一貫性、つまりすべてのユーザーが見るデータが同じであることを意味します。A は可用性を表し、利用可能なデータのコピーが常に見つかることを意味します。P は、ネットワーク停止などの障害を許容できるパーティション フォールト トレランスを表します。

1.2. 分散トランザクションと分散ロックの違い:

分散ロックは分散リソースのプリエンプションの問題を解決し、分散トランザクションとローカル トランザクションはプロセスの送信の問題を解決します。

1.3. トランザクションの 4 つの特徴:

アトミック

  • トランザクションはアトミックな操作シーケンス単位である必要があります。1 回の実行中に、トランザクションに含まれるすべての操作は正常に実行されるか、まったく実行されません。いずれかの操作が失敗すると、トランザクション全体がロールバックされます。すべての操作が実行された場合のみ、正常に実行されると、トランザクション全体がロールバックされ、ビジネスは成功します。

一貫性

  • トランザクションの実行によってデータベース データの整合性と一貫性が破壊されることはできません。トランザクションの実行前と実行後、データベースは一貫した状態にある必要があります。

隔離隔離

  • 同時環境では、同時トランザクションは互いに分離されており、1 つのトランザクションの実行が他のトランザクションによって干渉されることはありません。つまり、異なるトランザクションが同じデータを同時に操作する場合、各トランザクションは独自の完全なデータ空間を持ちます。つまり、トランザクション内で使用される操作とデータは他の同時トランザクションから分離され、同時に実行されるトランザクションは互いに干渉することができません。

  • SQL の 4 つのトランザクション分離レベル:

    (1) コミットされていない読み取り

允许脏读。如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,因此事务没有提交,与此同时,允许另一个事务也能够访问该数据。例如A将变量n从0累加到10才提交事务,此时B可能读到n变量从010之间的所有中间值。

(2) 送信されたものを読む

允许不可重复读。只允许读到已经提交的数据。即事务A在将n从0累加到10的过程中,B无法看到n的中间值,之中只能看到10。同时有事务C进行从1020的累加,此时B在同一个事务内再次读时,读到的是20

(3) 繰り返し読み取り可能

允许幻读。保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻时是一致的。禁止脏读、不可重复读。幻读即同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。保证B在同一个事务内,多次读取n的值,读到的都是初始值0。幻读,就是不同事务,读到的n的数据可能是0,可能10,可能是20

(4) 連載化

 最严格的事务,要求所有事务被串行执行,不能并发执行。

トランザクションの同時実行制御がない場合、データベースの同時操作で発生する可能性のある異常な状況を見てみましょう。

  • 失われた更新の 1 つのタイプ: 2 つのものが同じデータを読み取り、1 つはフィールド 1 を変更し、もう 1 つはフィールド 2 を変更します。後で送信されたものは、最初に送信されたフィールドを復元します。
  • タイプ II 更新喪失: 2 つのものが同じデータを読み取り、両方とも同じフィールドを変更し、後で送信されたものが最初に送信された変更を上書きします。
  • ダーティ リード: コミットされていない値が読み取られ、トランザクションがロールバックされるとダーティ リードが発生します。
  • 反復不可能な読み取り: 2 つのクエリの間で、データのコンテンツが別のトランザクションによって変更され、コンテンツの不整合が発生しました。
  • ファントム読み取り: 2 つのクエリの間で、別のトランザクションによってレコードが挿入または削除され、結果セットに不整合が生じます。

耐久性持続性

  • 耐久性: 永続性は、永続性とも呼ばれ、トランザクションが送信されると、データベース内の対応するデータに対する状態の変更が永続的であることを意味します。

  • システムクラッシュやマシンダウンが発生しても、データベースを再起動できれば、トランザクションが正常に終了したときの状態に戻すことができます。

1.4. MySQL ローカルトランザクション実装計画

ほとんどのシナリオでは、アプリケーションは 1 つのデータベースを操作するだけでよく、この場合のトランザクションはローカル トランザクション (ローカル トランザクション) と呼ばれます。ローカル トランザクションの ACID プロパティは、データベースによって直接サポートされています。

MySQL トランザクションについて学習した学生は、ローカル トランザクションを実現するために、MySQL がロールバック ログ、REDO ログ、MVCC、読み取り/書き込みロックなどの多くの作業を行ってきたことを知っているでしょう。

MySQLデータベースのトランザクション実装原理

MySQL の InnoDB (InnoDB は MySQL のストレージ エンジンです) を例として、単一データベースのトランザクション実装原理を紹介します。

InnoDB は、次のようにログとロックを通じてトランザクションの ACID 特性を保証します。

(1) データベース ロック メカニズムを通じてトランザクションの分離を確保します。

(2) REDO ログを通じてトランザクションの耐久性を確保します。

(3) Undo ログを通じてトランザクションのアトミック性を確保します。

(4) Undo Log を通じてトランザクションの一貫性を確保します。

Undo Log はトランザクションのアトミック性をどのように保証しますか?

具体的な方法は、データを操作する前に、データをある場所(データのバックアップが保存されている場所をアンドゥログと呼びます)にバックアップし、その後データを変更します。エラーが発生した場合、またはユーザーが Rollback ステートメントを実行した場合、システムは Undo ログ内のバックアップを使用して、データをトランザクション開始前の状態に復元できます。

REDO ログはトランザクションの耐久性をどのように保証しますか?

具体的な方法は次のとおりです。 REDO ログは、新しいデータのバックアップを記録します (Undo ログの反対)。トランザクションがコミットされる前に、REDO ログを永続化するだけでよく、データを永続化する必要はありません。システムがクラッシュすると、データは保持されませんが、REDO ログは保持されます。システムは、REDO ログの内容に基づいて、すべてのデータをクラッシュ前の状態に復元できます。

1.5. ダーティリード、ファントムリード、ノンリピートリード

複数のトランザクションが同時に動作すると、データベースではダーティリード、ファントムリード、ノンリピータブルリードという3つの問題が発生します。

1.5.1. ダーティリード

トランザクション A は、トランザクション B のコミットされていないデータを読み取ります。

トランザクション A がデータを読み取り、トランザクション B がデータを送信する前にデータを変更する前に、トランザクション A はデータを再度読み取り、トランザクション B が変更したデータを読み取ります。この時点でトランザクション B がデータを再度ロールバックまたは変更すると、その後コミットされます。 、トランザクション A によって読み取られたデータはダーティ データであるため、この状況をダーティ リード (Dirty Read) と呼びます。

ここに画像の説明を挿入します

1.5.2. ファントムリード

トランザクション A が範囲クエリを実行すると、トランザクション B は範囲条件を満たす新しいレコードを追加します。トランザクション A が再度条件に基づいて範囲クエリを実行すると、トランザクション B で送信された条件を満たす新しいレコードが検索されます (ファントム行) 。

ここに画像の説明を挿入します

1.5.3、非反復読み取り (Unrepeatable Read)

トランザクション A がデータを読み取った後、再度データを読み取ると、読み取ったデータがトランザクション B で変更または削除されていることがわかります。

ここに画像の説明を挿入します

ファントム読み取りと非再現性の違い:

ファントム読み取り: 同じトランザクションで、同じ条件下で 2 回クエリされたレコードの数が異なります;
ノンリピート可能読み取り: 同じトランザクションで、同じ条件で 2 回クエリされたデータが異なります。

1.6. トランザクション分離レベル

データベースでのトランザクションの同時実行によって引き起こされる問題を解決するために、標準 SQL 仕様では 4 つのトランザクション分離レベルが定義されています。各レベルは、トランザクション内で行われた変更と、トランザクション内およびトランザクション間で表示される変更を指定します。 。

一般に、分離レベルが低いほど高い同時実行性がサポートされ、システムのオーバーヘッドが低くなります。

MySQL システム パラメータを変更して、トランザクションの分離レベルを制御します。MySQL8 では、このパラメータはtransaction_isolation、MySQL5 では、このパラメータは tx_isolation です。

MySQL8:
-- 查看系统隔离级别:
SELECT @@global.transaction_isolation;

-- 查看当前会话隔离级别
SELECT @@transaction_isolation;

-- 设置当前会话事务隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

-- 设置全局事务隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

トランザクションの 4 つの分離レベル:

コミットされていない読み取り (READ UNCOMMITTED): すべてのトランザクションは、他のトランザクションのコミットされていない変更を参照できます。一般的にはほとんど使用されません。

READ COMMITTED: Oracle のデフォルトの分離レベル。トランザクションはお互いに送信された変更のみを参照できます。

反復可能な読み取り (REPEATABLE READ): MySQL のデフォルト分離レベル、同じトランザクション内の複数のクエリは同じデータ行を参照します。反復不可能な読み取りは解決できますが、ファントム読み取りが発生する可能性があります。

SERIALIZABLE: 最も高い分離レベル、トランザクションのシリアル実行。前のトランザクションが実行された後、後続のトランザクションが実行されます。読み取られたデータはすべてロックされるため、多くのタイムアウトやロック競合の問題が発生します。

ここに画像の説明を挿入します

2. 分散トランザクションの基本概念

2.1. 分散環境におけるトランザクションの複雑さ

ストレージ側の多様性。

1つ目は、ストレージの多様性です。ローカルトランザクションの場合、すべてのデータは同じDBに分類されますが、分散トランザクションの場合、データは複数のDBに分類される場合や、Redis、MQなどに分類される場合があります。

以下の図に示すように、ストレージエンドの多様性:

ここに画像の説明を挿入します

トランザクションリンクのスケーラビリティ

ローカル トランザクションの場合、通常、すべてのトランザクション関連のビジネス操作は Service メソッドにカプセル化されます。分散型の場合、リクエスト リンクは拡張されて長くなり、操作は線形またはメッシュ状の複数のサービスに分割され、全体を形成するためにネットワーク通信に依存します。この場合、問題はさらに複雑になることは間違いありません。

次の図に示すように、トランザクション リンクのスケーラビリティ:

ここに画像の説明を挿入します

上記の 2 つの複雑さを考慮すると、ローカル トランザクションのようなほぼ非侵襲的な方法で、さまざまなストレージ メディアやさまざまな複雑なリンクを満たすことができる統合分散トランザクション ソリューションを期待することは非現実的です。

少なくとも現時点では、非常に成熟した解決策はありません。したがって、通常の状況下では、分散条件下では、トランザクションは分割されて解決され、状況に応じて異なる解決策が採用されます。

2.2. 分散トランザクションとは何ですか?

分散システムの場合、分散システム内のデータの一貫性を確保し、サブシステム内のデータが常に一貫していることを確認し、ビジネス上の問題を回避する必要があります。分散システムでは、数値のペアは同時に成功するか失敗するかのいずれかであり、全体的なトランザクションである必要があります。

分散トランザクションとは、トランザクションの参加者、トランザクションをサポートするサーバー、リソース サーバー、およびトランザクション マネージャーがそれぞれ異なる分散システムの異なるノードに配置されていることを意味します。

簡単に言えば、分散システムにおける大規模な操作は、さまざまな小さな操作で構成されます。これらの小さな操作は、さまざまなサービス ノードに分散され、さまざまなアプリケーションに属します。分散トランザクションは、これらの小さな操作がすべて成功することを保証する必要があります。そうしないと、すべてが失敗します。

例: 電子商取引 Web サイトで、ユーザーが商品を注文するとき、注文テーブルに注文データを作成し、同時に現在の商品の在庫残数を注文テーブルで変更する必要があります。在庫テーブルには 2 つのステップがあります: 追加するステップと変更するステップです。これら 2 つのステップが同時に成功するか失敗することを確認する必要があります。そうしないと、ビジネス上の問題が発生します。

トランザクション メカニズムを実装する場合、ローカル トランザクションと分散トランザクションを含むトランザクションの ACID 特性を考慮する必要があります。分散トランザクションの場合、すべてを十分に満たすことができない場合でも、サポートの範囲を考慮する必要があります。

典型的な分散トランザクション シナリオ:

クロスデータベース トランザクション
クロスデータベース トランザクションとは、アプリケーションが特定の機能のために複数のライブラリを操作する必要があり、異なるビジネス データが異なるライブラリに格納されることを指します。著者は、9 つ​​の図書館が同時に運営される比較的複雑なビジネスを見てきました。

次の図は、2 つのライブラリを同時に操作するサービスを示しています。
ここに画像の説明を挿入します

データベースとテーブルの分割
通常、データベースのデータ量が大きい場合、または将来予想されるデータ量が比較的大きい場合、データベースは水平方向、つまりデータベースとテーブルに分割されます。

次の図に示すように、データベース B は 2 つのライブラリに分割されています。
ここに画像の説明を挿入します

サブデータベースとサブテーブルの場合、一般的な開発者は SQL 操作の複雑さを軽減するために何らかのデータベース ミドルウェアを使用します。

たとえば、SQL の場合: user(id,name) に値 (1, "tianshouzhi")、(2, "wangxiaoxiao") を挿入します。このSQLは単一データベースを操作するための構文であり、単一データベースの場合にはトランザクションの整合性を保証することができます。

ただし、サブデータベースとテーブルの分割により、開発者はレコード No. 1 をサブデータベース 1 に挿入し、レコード No. 2 をサブデータベース 2 に挿入したいと考えています。したがって、データベースミドルウェアは、それを2つのSQLに書き換えて、それぞれを2つの異なるサブデータベースに挿入する必要がありますが、このとき、2つのデータベースが成功するか失敗するかを保証する必要があるため、基本的にすべてのデータベースミドルウェアはこの問題に直面します。分散トランザクションの問題。

マイクロサービス
マイクロサービス アーキテクチャは、現在比較的人気のある概念です。たとえば、上記の著者が述べたケースでは、アプリケーションは 9 つのライブラリを同時に実行します。このようなアプリケーションのビジネス ロジックは非常に複雑でなければならず、開発者にとって大きな課題です。アプリケーションは、異なる独立したサービスに分割する必要があります。ビジネス ロジックを簡素化するため。分割後、独立したサービスは RPC フレームワークを介してリモート呼び出しを行い、相互に通信します。次の図は、3 つのサービスが相互に呼び出しを行うアーキテクチャを示しています。

ここに画像の説明を挿入します

サービス A は、ある機能を実行するためにデータベースを直接操作する必要があり、サービス B とサービス C を同時に呼び出す必要があります。サービス B は 2 つのデータベースを同時に操作し、サービス C はライブラリも操作します。複数のデータベースに対するこれらのクロスサービス操作が成功するか失敗するかを確認する必要があり、実際、これが最も典型的な分散トランザクション シナリオと言えます。

分散トランザクション実装ソリューションではパフォーマンスの問題を考慮する必要があり、ACID 特性を厳密に保証するためにパフォーマンスが大幅に低下すると、高速応答が必要な一部のビジネスでは受け入れられなくなります。

3. CAP定理

3.1. 分散トランザクションの理論的基礎

データベース トランザクションにおける ACID の 4 つの主要な特徴は、分散トランザクションの実際のニーズを満たすことができず、現在、一部の新しい専門家がいくつかの新しい理論を提唱しています。

3.2. CAP 定理

CAP定理は、カリフォルニア大学バークレー校のエリック・ブリュワー教授によって提唱され、WEBサービスは以下の3つの属性を同時に満たすことができないと指摘しました。

  • 一貫性: クライアントは、一連の操作が同時に発生する (有効になる) ことを知っています。
  • 可用性: すべての操作は予測可能な応答で終了する必要があります
  • パーティション トレランス (パーティション トレランス): 1 つのコンポーネントが利用できない場合でも、操作は完了できます。

具体的には、分散システムでは、Web アプリケーションは最大でも上記 2 つの属性のみを同時にサポートできます。したがって、設計者は一貫性と使いやすさのどちらかを選択する必要があります。

2000年7月にエリック・ブリュワー教授が提案したのは単なる推測に過ぎず、2年後、MITのセス・ギルバートとナンシー・リンチがCAP理論を理論的に証明し、分散システムはせいぜいCAPの要件を満たせるのは2項目だけである。その後、CAP 理論は分散コンピューティングの分野で正式に認識される定理となりました。

ここに画像の説明を挿入します

したがって、CAP 定理はこれまでのところ分散システムに適用できます。

CAP の一貫性、可用性、およびパーティション耐性は次のとおりです。

一貫性

データの一貫性とは、「すべてのノードが同時に同じデータを参照する」ことを指します。つまり、更新操作が成功してクライアントに返された後、同時にすべてのノードのデータは完全に一貫しており、中間状態は存在しません。存在する。

分散環境では、一貫性とは、複数のコピーが一貫性を保つ能力を指します。一貫性の要件の下では、システムが一貫したデータ状態で更新操作を実行する場合、システムのデータが依然として一貫した状態にあることを保証する必要があります。

たとえば、電子商取引システムのユーザーが注文を行う場合、ユーザーの注文操作が完了した後、在庫の削減、ユーザー資本口座の控除、ポイントの増加などの操作が一貫している必要があります。在庫は減っているのに、ユーザーの資本口座が差し引かれず、ポイントが増加しない、という状況はあり得ません。これが発生した場合は、矛盾しているとみなされます。

データの整合性は、強整合性、弱整合性、結果整合性に分けられます。

上で説明したように、クライアントに表示されるデータが常に一貫していることを保証できる場合、それは強整合性と呼ばれます。
中間状態の存在が許可され、一定期間後にデータが最終的に一貫性を持つことのみが必要な場合、それは最終的な一貫性と呼ばれます。
また、部分的なデータの不整合が許容される場合、それを弱い整合性と呼びます。

可用性

システムが提供するサービスは常に利用可能である必要があり、ユーザーの操作リクエストごとに限られた時間内に結果が返される必要があります。

2 つの測定寸法:

(1) 限られた時間内で
、システムはユーザーからの操作要求に対して、指定された時間 (応答時間) 以内に対応する処理結果を返すことができなければならず、この時間を超えるとシステムは使用不能とみなされます。つまり、ユーザーを失望させないために、応答時間は妥当な値内でなければなりません。

想像してみてください。分散トランザクションの一貫性を確保するために注文操作が完了するまでに 10 分かかる場合、ユーザーは明らかにそれに耐えられません。

(2) 正常な結果を返す
: システムは、ユーザーのリクエストの処理が完了した後、正常な応答結果を返す必要があります。通常、通常の応答結果は、ユーザーを混乱させるような戻り結果ではなく、要求の処理結果、つまり成功または失敗を明確に反映します。たとえば、OutOfMemory などのシステム エラーが返された場合、システムは使用できないとみなされます。

「応答結果」も可用性を示す非常に重要な指標であり、システムは、ユーザーのリクエストの処理が完了した後、結果が成功か失敗かに関係なく、通常の応答結果を返す必要があります。

パーティション許容度

つまり、分散システムでネットワーク分割障害が発生した場合でも、ネットワーク環境全体に障害が発生しない限り、一貫性と可用性を満たす外部サービスを確実に提供できる必要があります。

ネットワーク分断とは、分散システムにおいて、異なるノードが異なるサブネットワーク(計算機室/リモートネットワーク)に分散され、何らかの特別な理由により、これらのサブネットワーク間でネットワークが切断された状態となることを指しますが、各サブネットワークは、ネットワーク 内部ネットワークは正常であるため、システム全体のネットワーク環境がいくつかの孤立した領域に分割されています。分散システムを構成する各ノードの参加と離脱は、特別なネットワーク分割とみなすことができます。

3.3. CAPの適用

諦めてP

パーティションのフォールト トレランスを放棄すると、システムの分散とスケーラビリティも放棄することになります。

諦めるA

可用性を放棄すると、ネットワークの分断などの障害が発生した際に、影響を受けるサービスは一定時間待機する必要があり、この間、ポリシーサービスを外部に提供できなくなります。利用できません。

諦めるC

整合性が放棄された場合 (ここでは強整合性を指します)、システムはデータがリアルタイムの整合性を維持していることを保証できません。データが最終的な整合性に達するまでには時間枠があり、その時間枠内ではデータは不整合になります。

分散システムの場合、P を放棄することはできないため、アーキテクトは通常、可用性と一貫性の間でトレードオフを検討します。

CAP 理論は次のことを示しています。
現在、多くの大規模な Web サイトとアプリケーションが分散方式で展開されており、分散シナリオにおけるデータの一貫性の問題は常に重要なトピックです。

CAP 理論に基づいて、多くのシステムは設計の開始時に次の 3 つの間のトレードオフを行う必要があります。

分散システムは、一貫性、可用性、およびパーティション耐性を同時に満たすことはできず、同時に 2 つだけを満たすことができます。インターネット分野のほとんどのシナリオでは、システムの高可用性と引き換えに強い一貫性を犠牲にする必要があり、多くの場合、システムは最終的な一貫性を確保するだけで十分です。

Q: 分散システムでは整合性と可用性の両方を保証できないのはなぜですか?

回答: まず前提がありますが、分散システムの場合、パーティションの耐障害性は最も基本的な要件であるため、基本的に分散システムを設計する際には一貫性 (C) と可用性 (A) のどちらかを選択するしかありません。

整合性が保証されている場合 (C): ノード N1 および N2 の場合、N1 にデータを書き込むときは、N2 の操作を一時停止する必要があります。N1 が N2 にデータを同期する場合にのみ、N2 の読み取りおよび書き込みリクエストが可能になり、N2 はブロックされます。一時停止操作中のクライアントは失敗またはタイムアウトを受け取ります。明らかに、これはユーザビリティとは正反対です。

可用性 (A) が保証されている場合: N2 の読み取りおよび書き込み操作を一時停止することはできませんが、N1 が同時にデータを書き込んでいる場合、これは整合性要件に違反します。

3.4. CAP のトレードオフ

CAP 理論を通じて、一貫性、可用性、パーティション耐障害性の 3 つの特性を同時に満たすことはできないことがわかります。では、どれを破棄すべきでしょうか?

ほとんどの大規模なインターネット アプリケーション シナリオでは、多数のホストと分散した展開があり、現在のクラスターの規模はますます大きくなっているため、ノード障害やネットワーク障害は正常であり、サービスの可用性が N 9 に達することを保証する必要があります。 、P と A は保証され、C は破棄されます (次善の策は結果整合性を確保することです)。顧客体験に影響を与える箇所もありますが、ユーザーフローを引き起こすほどではありません。

金銭が関係し、妥協の許されないシナリオの場合、C はそれを保証する必要があります。ネットワークに障害が発生した場合は、CA を確保し、P を放棄するために、サービスを停止することをお勧めします。国内の銀行業界ではここ数年で10件以上の事故が発生しているようだが、その影響は大きくなく、報道も少なく、一般の人々の知るところも少なかった。CPを確保してAを捨てるという選択肢もあります。たとえば、ネットワーク障害は読み取りのみであり、書き込みは発生しません。

3.5、CAPとACIDのAとCは全く異なります

Aとの違い:

  • ACID の A は原子性 (Atomicity) を指します。これは、トランザクションが分割できない最小の作業単位とみなされ、トランザクション内のすべての操作が正常に送信されるか、失敗後にロールバックされることを意味します。
  • CAP の A は可用性を指します。可用性は、クラスター内の一部のノードに障害が発生した後でもクラスター全体がクライアントの読み取りおよび書き込み要求に応答できるかどうかを指します。

Cとの違い:

  • ACID の整合性はデータベース ルールに関するものであり、データベースは常に、ある整合性のある状態から別の整合性のある状態に遷移します。
  • CAP の一貫性は、分散マルチサーバー間でデータをレプリケートし、これらのサーバーが同じデータを持つようにすることです。ネットワーク速度の制限のため、異なるサーバーでのこのレプリケーションにかかる時間は固定されていません。クラスターはクライアントを編成することによって異なるデータを表示します。ノード上で同期されていないデータは、分散フィールドにおける一貫性の概念である論理ビューを維持します。

要約すれば:

ACID の整合性はトランザクション実行前後のデータベースの整合性を指しますが、CAP の整合性は分散ノード上のデータの整合性を指します。背景が違うので比較することはできません

4.BASE定理

CAP は分散システム設計理論であり、BASE は CAP 理論における AP ソリューションの拡張であり、C に対して採用する方法と戦略は結果整合性を確保することです。

eBay のアーキテクトである Dan Pritchett は、大規模分散システムの実践的な要約に由来しています。彼は ACM に関する記事を発表し、BASE 理論を提案しました。BASE 理論は、CAP 理論の拡張です。中心となるアイデアは、たとえ強い整合性 (Strong Consistency、CAP Consistency は強い整合性) ですが、アプリケーションは適切な方法を使用して最終整合性 (Eventual Consitency) を実現できます。

4.1. BASE 定理

BASE は、Basic Available、Soft state、そして最終的に整合性のある 3 つのフレーズの略語です。BASE は CAP 定理に基づいて進化しており、強整合性をすぐに実現することはできないが、各アプリケーションがそれぞれのビジネス特性に応じて適切な方法を採用して、システムの最終的な整合性を実現できるという基本的な考え方を持っています。

1. 基本的に利用可能

基本可用是指分布式系统在出现不可预知的故障的时候,允许损失部分可用性,但不等于系统不可用。

(1) 応答時間のロス

当出现故障时,响应时间增加

(2) 機能喪失

   当流量高峰期时,屏蔽一些功能的使用以保证系统稳定性(服务降级)

2. ソフト状態

これは、システム内のデータが中間状態で存在できることを意味し、この中間状態の存在はシステム全体の可用性に影響を与えないと考えられています。

ハード状態とは対照的に、システム内のデータが中間状態で存在することが許可されていることを意味し、この中間状態の存在はシステム全体の可用性、つまりシステムのプロセスに影響を与えないと考えられています。システムが異なるノードのデータ コピー間でデータを同期できるようにするのに時間がかかります。

3. 結果的に一貫性がある(最終的な一貫性)

システム内のすべてのデータ コピーは、一定期間の同期後に最終的に一貫した状態に到達できることが強調されます。その本質は、システムは最終データの一貫性を保証する必要があるが、システム データの強力な一貫性をリアルタイムで保証する必要はないということです。

最終的な一貫性は次のタイプに分類できます。

(1) 因果的整合性(因果的整合性)
とは、プロセスAがデータを更新した後にプロセスBに通知すると、プロセスBによるデータの範囲がプロセスAが更新した最新の値となることを意味します。
(2) 書き込みの読み取り:
プロセス A がデータを更新した後は、更新された最新の値に常にアクセスできます。
(3) セッションの一貫性 (Session Consistency) は、
セッション内のデータの一貫性をフレーム化し、セッション内の読み取りと書き込みの一貫性を実現します。つまり、更新実行後、クライアントは常に同じセッション内のデータの最新の値を読み取ることができます。
(4) 単調な読み取り一貫性 (Monotonic Read Consistency)
プロセスがシステムからデータ項目の特定の値を読み取る場合、システムは、プロセスによる後続のデータ アクセスに対して古い値を返してはなりません。
(5) 単調な書き込み一貫性:
システムは、同じプロセスからの書き込み操作が順番に実行されることを保証する必要があります。
BASE 理論は、一貫性を犠牲にして可用性を獲得することを提案しており、データが一定期間不整合であっても、最終的には一貫した状態に達することを許容します。

4.2. BASE 理論の特徴:

BASE 理論は、大規模で可用性が高く、スケーラブルな分散システムを指向しており、従来の ACID の特性とは対照的です。

ACID の強整合性モデルとはまったく異なりますが、強整合性を犠牲にして可用性を獲得し、一定期間データの不整合を許容しますが、最終的には整合性のある状態に達します。

しかし同時に、実際の分散シナリオでは、ビジネス ユニットやコンポーネントごとにデータの整合性に対する要件が異なるため、特定の分散システム アーキテクチャの設計プロセスでは、ACID の特性と BASE 理論が組み合わされることがよくあります。

4.3. BASE理論とCAPの関係

BASE 理論は、CAP における一貫性と可用性の間のトレードオフの結果であり、大規模なインターネット システムにおける分散慣行の概要から派生し、CAP 理論に基づいて徐々に進化しています。BASE 理論の中心となる考え方は、たとえ強整合性が達成できなくても、各アプリケーションは自身のビジネス特性に応じて適切な方法を採用し、システムの最終的な整合性を実現できるというものです。

BASE 理論は、実際には CAP 理論、主に AP の拡張および補足です。データの可用性を確保するために、データの強力な一貫性が犠牲になり、中間の読み込みは発生しますが、データは最終的に一貫性を保ちます。

4.4. ACID と BASE の違いと関連性

ACID は、従来のデータベースで一般的に使用されている設計概念であり、強整合性モデルを追求します。BASE は大規模な分散システムをサポートし、強整合性を犠牲にして高可用性を獲得することを提案しています。

ACID と BASE は正反対の 2 つの設計理念を表しており、分散システム設計のシナリオでは、システム コンポーネントの整合性要件が異なるため、ACID と BASE は組み合わせて使用​​されます。

6. 分散トランザクションの分類

分散シナリオでは、複数のサービスが 1 つのプロセスを同時に処理します。たとえば、電子商取引の注文シナリオでは、支払いには支払いサービスが必要で、在庫サービスは在庫を差し引き、注文サービスは注文を生成し、物流サービスは物流情報を更新します。特定のサービスが実行できなくなったり、ネットワーク障害によりリクエストが失われたりすると、システム全体でデータの不整合が発生する可能性があります。

上記のシナリオは分散一貫性の問題ですが、最終的には、分散一貫性の根本原因はデータの分散操作にあり、これによりデータの原子性を保証できないローカル トランザクションが発生します。

分散一貫性の問題を解決するには 2 つの方法があります。1 つは分散トランザクションであり、もう 1 つはビジネス プロセスを通じて分散トランザクションを回避しようとすることです。分散トランザクションは問題を直接解決しますが、ビジネス回避は実際に問題を解決します(質問者)。実際、実際のビジネス シナリオでは、ビジネス回避がそれほど面倒な前提ではない場合、最もエレガントな解決策はビジネス回避です。

分散トランザクション実装ソリューションは、次の種類の観点から、厳格なトランザクションと柔軟なトランザクションに分類されます。

  • CAPを満たす厳格な事柄のCP理論

  • 柔性事务满足BASE理论(基本可用,最终一致)

6.1、刚性事务

刚性事务:通常无业务改造,强一致性,原生支持回滚/隔离性,低并发,适合短事务。

原则:刚性事务满足足CAP的CP理论

刚性事务指的是,要使分布式事务,达到像本地式事务一样,具备数据强一致性,从CAP来看,就是说,要达到CP状态。

刚性事务:XA 协议(2PC、JTA、JTS)、3PC,但由于同步阻塞,处理效率低,不适合大型网站分布式场景。

6.2、柔性事务

柔性事务指的是,不要求强一致性,而是要求最终一致性,允许有中间状态,也就是Base理论,换句话说,就是AP状态。

与刚性事务相比,柔性事务的特点为:有业务改造,最终一致性,实现补偿接口,实现资源锁定接口,高并发,适合长事务。

柔性事务分为:

  • 补偿型
  • 异步确保型
  • 最大努力通知型。

柔性事务:TCC/FMT、Saga(状态机模式、Aop模式)、本地事务消息、消息事务(半消息)

6.3、刚性事务:XA模型、XA接口规范、XA实现

6.3.1、XA模型 或者 X/Open DTP模型

X/OPEN是一个组织.X/Open国际联盟有限公司是一个欧洲基金会,它的建立是为了向UNIX环境提供标准。它主要的目标是促进对UNIX语言、接口、网络和应用的开放式系统协议的制定。它还促进在不同的UNIX环境之间的应用程序的互操作性,以及支持对电气电子工程师协会(IEEE)对UNIX的可移植操作系统接口(POSIX)规范。

X/Open DTP(Distributed Transaction Process) 是一个分布式事务模型。这个模型主要使用了两段提交(2PC - Two-Phase-Commit)来保证分布式事务的完整性。

在X/Open DTP(Distributed Transaction Process)模型里面,有三个角色:

  • ​ AP: Application,应用程序。也就是业务层。哪些操作属于一个事务,就是AP定义的。

  • ​ TM: Transaction Manager,事务管理器。接收AP的事务请求,对全局事务进行管理,管理事务分支状态,协调RM的处理,通知RM哪些操作属于哪些全局事务以及事务分支等等。这个也是整个事务调度模型的核心部分。

  • ​ RM:Resource Manager,资源管理器。一般是数据库,也可以是其他的资源管理器,如消息队列(如JMS数据源),文件系统等。

ここに画像の説明を挿入します

XA把参与事务的角色分成AP,RM,TM。

AP,即应用,也就是我们的业务服务。

RM指的是资源管理器,即DB,MQ等。

TM则是事务管理器。

AP自己操作TM,当需要事务时,AP向TM请求发起事务,TM负责整个事务的提交,回滚等。

XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口。XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。

XA之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲(参考Fischer等的论文),两台机器理论上无法达到一致的状态,需要引入一个单点进行协调。事务管理器控制着全局事务,管理事务生命周期,并协调资源。资源管理器负责控制和管理实际资源(如数据库或JMS队列)

ここに画像の説明を挿入します

6.3.2、XA规范

什么是XA

用非常官方的话来说:

  • XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准。

  • XA 规范 描述了全局的事务管理器与局部的资源管理器之间的接口。 XA规范 的目的是允许的多个资源(如数据库,应用服务器,消息队列等)在同一事务中访问,这样可以使 ACID 属性跨越应用程序而保持有效。

  • XA 规范 使用两阶段提交(2PC,Two-Phase Commit)协议来保证所有资源同时提交或回滚任何特定的事务。

  • XA 仕様は 1990 年代初頭に提案されました。現在、ほとんどすべての主流データベースが XA 仕様のサポートを提供しています。

XA仕様は、X/OPENによって提案された分散トランザクション処理仕様です。XA は TM と RM の間の通信インターフェイスを標準化し、TM と複数の RM の間に双方向通信ブリッジを形成し、複数のデータベース リソースの下で 4 つの ACID 特性を保証します。Oracle、DB2、mysql など、現在よく知られているデータベースはすべて XA インターフェイスを実装しており、RM として使用できます。

XA は、強い整合性を備えたデータベースの分散トランザクションです。プロセス全体で、データはロックされます。つまり、準備からコミット、ロールバックまでのプロセス全体で、TM は常にデータベースのロックを保持します。他の人が望む場合は、TM がデータベースのロックを保持します。データベース内のこのデータはロックが解除されるまで待つ必要があり、トランザクションが長くなる危険性があります。

以下の関数により、トランザクション マネージャーはリソース マネージャーに対して操作を実行できます。
1) xa_open、xa_close: リソース マネージャーとの接続を確立および閉じます。
2)xa_start,xa_end: ローカルトランザクションを開始および終了します。
3) xa_prepare、xa_commit、xa_rollback: ローカル トランザクションを事前コミット、コミット、ロールバックします。
4) xa_recover: コミット済みのトランザクションをロールバックします。
5) ax_ で始まる関数により、リソース マネージャーがトランザクション マネージャーに動的に登録され、XID (TRANSACTION IDS) で動作することが可能になります。
6) ax_reg、ax_unreg; リソース マネージャーが TMS (TRANSACTION MANAGER SERVER) に動的に登録または登録解除できるようにします。

XAの各ステージの処理の流れ

ここに画像の説明を挿入します

6.3.3. XAプロトコルの実装

ここに画像の説明を挿入します

2PC/3PCプロトコル

2 フェーズ コミット (2PC) プロトコルは、XA 仕様によって定義されたデータ整合性プロトコルです。

3 フェーズ コミット (3PC) プロトコルは、2PC プロトコルの拡張です。

セット

Seata は、マイクロサービス アーキテクチャの下で高性能で使いやすい分散トランザクション サービスを提供することに特化したオープンソースの分散トランザクション ソリューションです。Seata はユーザーに AT、TCC、SAGA、および XA トランザクション モードを提供します

Seata がオープンソース化される前は、対応する Seata の内部バージョンがアリババ経済内で分散型の一貫したミドルウェアの役割を果たし、何年にもわたって経済がダブル 11 を乗り切るのに貢献し、各 BU のビジネスを強力にサポートしていました。商用製品の GTS は、Alibaba Cloud および Financial Cloud で販売されています。

Jta仕様

Java プラットフォーム上のトランザクション仕様として、JTA (Java Transaction API) も XA トランザクションのサポートを定義しています。実際、JTA は XA アーキテクチャに基づいてモデル化されています。JTA では、トランザクション マネージャーは javax.transaction.TransactionManager インターフェイスとして抽象化され、そして、基礎となるトランザクション サービス (つまり、JTS) を介して。他の多くの Java 仕様と同様に、JTA はインターフェイスのみを定義し、具体的な実装は提供者 (J2EE メーカーなど) によって提供されます。現在、JTA の実装は主に次の種類で構成されます。 J2EE コンテナ
(JBoss)
2. 独立した JTA 実装: JOTM、Amitikos など。

これらの実装は、分散トランザクション保証を提供するために J2EE アプリケーション サーバーを使用しない環境で使用できます。Tomcat、Jetty、一般的な Java アプリケーションなど。

JTS仕様

トランザクションはプログラミングに欠かせないものであり、Java ではトランザクション開発を標準化するために、JTA および JTS というトランザクションに関する仕様が追加されました。

JTA は、いくつかの主要な役割 (TransactionManager、UserTransaction、Transaction、XAResource) が合意された一連のインターフェイスを定義し、TransactionManager へのトランザクションの委任など、これらの役割間で従う必要がある仕様を定義します。

JTS も一連の仕様です。JTA は役割間の対話を必要とすることは上で述べましたが、役割間の対話はどのように行うべきでしょうか? JTS は、インタラクションの詳細を指定する仕様です。

一般的に、JTA はフレームワークの観点からプログラム ロールのインターフェイスについて合意し、JTS は特定の実装の観点からプログラム ロール間のインターフェイスについて合意し、両方とも独自の義務を実行します。

Amitikos 分散トランザクションの実装

Amitikos には 2 つのよく知られた分散ビジネス製品があります。

TransactionEssentials:オープンソースの無料製品
ExtremeTransactions:商用版、有料
これら 2 つの製品の関係は下図のとおりです。

ここに画像の説明を挿入します

ご覧のとおり、オープン ソース バージョンは JTA/XA、JDBC、および JMS トランザクションをサポートしています。

atimikos は Spring トランザクションとの統合もサポートしています。

Spring トランザクション マネージャーの最上位の抽象化は PlatformTransactionManager インターフェイスであり、重要な実装クラスを提供します。

DataSourceTransactionManager: ローカル トランザクションの実装に使用
JTATransactionManager: 分散トランザクションの実装に使用
明らかに、ここで設定する必要があるのは JTATransactionManager です。

public class JTAService {
    
      
    @Autowired   
    private UserMapper userMapper;//操作db_user库   
    @Autowired  
    private AccountMapper accountMapper;//操作db_account库  

    @Transactional   
    public void insert() {
    
        
        User user = new User();     
        user.setName("wangxiaoxiao");     
        userMapper.insert(user);  
        //模拟异常,spring回滚后,db_user库中user表中也不会插入记录     
        Account account = new Account();     
        account.setUserId(user.getId());    
        account.setMoney(123456789);    
        accountMapper.insert(account); 
    }
}

XA の主な制限

すべてのデータ ソースを取得する必要があり、データ ソースが XA プロトコルをサポートしている必要があります。現在、MySQL の InnoDB ストレージ エンジンのみが XA プロトコルをサポートしています。
パフォーマンスは比較的悪く、強い整合性を確保するために関連するすべてのデータをロックする必要があり、長時間のトランザクションが発生します。

シータATモード

シータATモードは2pcモードを強化したモードです。

AT モード: 常にテーブルをロックしない、2 フェーズ コミット プロトコルの進化版

フェーズ 1: ビジネス データとロールバック ログ レコードが同じローカル トランザクションでコミットされ、ローカル ロックと接続リソースが解放されます。
フェーズ 2: コミットは非同期であり、非常に迅速に完了します。または、1 段階のロールバック ログによるロールバック逆補償

LCN(2本)

TX-LCN、公式ドキュメント、github、星 3,000 個以上、5.0 以降、フレームワークは LCN (2pc)、TCC、TXC の 3 つのトランザクション モードと互換性があるため、LCN モードを区別するために、LCN 分散トランザクションはこれにより、TX-LCN 分散型ビジネス フレームワークの名前が変更されました。

TX-LCN はトランザクション調整フレームワークとして位置付けられており、フレームワーク自体はトランザクションを生成するのではなく、ローカル トランザクションの調整役としてトランザクションの一貫性の効果を実現します。

TX-LCN には主に、Tx-Client(TC) と Tx-Manager™ の 2 つのモジュールがあります。

TM (Tx-Manager): 独立したサービスであり、分散トランザクションのコントローラーであり、分散トランザクションの送信を調整し、ロールバックします。
TC (Tx-Client): ビジネス システムによって統合され、トランザクションの開始者と参加者はすべて TxClient によって管理されます。端末制御

6.4、2PC(標準XAモデル)

2PC は Two-Phase Commit、2 フェーズ コミットです。

6.4.1 詳細説明: 2 段階

分散アーキテクチャに基づくすべてのノードがトランザクション処理時に原子性と一貫性を維持できるようにするために、データベース分野で広く使用されています。ほとんどのリレーショナル データベースは、2PC に基づいて分散トランザクション処理を完了します。

名前が示すように、2PC は 2 つの処理段階に分かれています。第 1 段階: トランザクション要求の送信、第 2 段階: トランザクション送信の実行です。

フェーズ 1 がタイムアウトするか例外が発生した場合、2PC フェーズ 2: トランザクションを中断します。

フェーズ 1: トランザクション リクエストを送信する

ビジネスに関するお問い合わせ。コーディネーターはトランザクションの内容をすべての参加者に送信し、コミット操作を実行できるかどうかを尋ね、各参加者の応答を待ち始めて
トランザクションを実行します。各参加者ノードはトランザクション操作を実行し、元に戻す操作とやり直し操作をローカル トランザクション ログにカウントします。
各参加者はトランザクション クエリに対する応答をコーディネーターにフィードバックします。正常に実行された場合は Yes を返し、それ以外の場合は No を返します。

フェーズ 2: トランザクションの送信を実行する

コーディネーターはフェーズ 2 で、トランザクションのコミット操作を最終的に実行するかどうかを決定します。この段階には 2 つの状況が含まれます。

トランザクションコミットを実行する

すべての参加者が「はい」と応答すると、トランザクションのコミットが実行されます。

コミットリクエストを送信します。コーディネーターはコミット要求をすべての参加者に送信し、
トランザクションがコミットされます。コミット要求を受信した後、参加者は正式にトランザクション送信操作を実行し、送信操作の完了後、トランザクション実行全体で占有されていたリソースを解放し、トランザクション送信結果をフィードバックします
参加者がトランザクションの送信を完了すると、書き込みコーディネーターが確認の Ack メッセージを送信し、
トランザクションが完了します。コーディネーターは、すべての参加者から Ack を受信した後、トランザクションを完了します。

ここに画像の説明を挿入します

フェーズ 2: トランザクションの中断

参加者の 1 人がコーディネーターに「いいえ」応答を送信するか、待機時間がタイムアウトになると、常に問題が発生します。コーディネーターは、すべての参加者から「はい」の応答を受信できない限り、トランザクションを中止します。

ロールバックリクエストを送信します。コーディネーターは、すべての参加者にロールバック要求を送信します (
ロールバック)。リクエストを受信した後、参加者はローカルの Undo 情報を使用してロールバック操作を実行します。ロールバックが完了すると、トランザクションによって占有されていたシステム リソースが解放され、
ロールバック結果がフィードバックされます。ロールバック操作が完了すると、参加者は Ack メッセージをコーディネーターに送信し、
トランザクションを中断します。コーディネーターがすべての参加者からロールバック Ack メッセージを受信すると、トランザクションは中断されます。

ここに画像の説明を挿入します

6.4.2、2pc は分散データの強整合性の問題を解決します

名前が示すように、2 フェーズ コミットは、分散トランザクションを処理するときに、投票 (投票フェーズ、準備フェーズと呼ばれることもあります) とコミット フェーズの 2 つのフェーズに分割されます。

2pc にはトランザクションコーディネーター (seata、atomikos、lcn) とトランザクション参加者という 2 つの役割があり、トランザクション参加者は通常アプリケーション データベースを参照します。

ここに画像の説明を挿入します

6.4.3 2PC 第 2 段階提出の特徴

2PC ソリューションは単一アプリケーションに適しています

2PC ソリューションには、複数のデータベース (リソース マネージャー) のトランザクションを調整する責任を負うトランザクション マネージャーの役​​割があり、トランザクション マネージャーは最初に各データベースに準備ができているかどうかを尋ねます。各データベースが OK と応答した場合、トランザクションは正式に送信され、各データベースで操作が実行されます。いずれかのデータベースが OK を応答しなかった場合、トランザクションはロールバックされます。

ここに画像の説明を挿入します

2PC ソリューションは、単一アプリケーション内の複数のライブラリにわたる分散トランザクションにより適しています。また、複雑なトランザクションを処理するためにデータベース レベルに大きく依存するため、効率が非常に低く、同時実行性の高いシナリオには明らかに適していません。

2PC ソリューションが実際に使用されることはほとんどありませんが、一般に、このような操作がシステム内の複数のライブラリにわたって発生する場合、それは違法です。ここで紹介できるのは、大規模なシステムが数百、数十のサービスに分割されたマイクロサービスです。一般的に、当社の規制と仕様では、各サービスが対応する独自のデータベースのみを操作できることが求められています。

他のサービスに対応するライブラリを操作したい場合、他のサービスのライブラリへの直接接続は許可されておらず、マイクロサービスアーキテクチャの仕様に違反します。 up. such a set of services can can 管理や管理ができないと、他人によってデータが修正されたり、自分のデータベースが他人によって書き込まれてしまったりする可能性があります。

如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。

2PC具有明显的优缺点:

优点主要体现在实现原理简单;
缺点比较多:

  • 2PC的提交在执行过程中,所有参与事务操作的逻辑都处于阻塞状态,也就是说,各个参与者都在等待其他参与者响应,无法进行其他操作;

  • 协调者是个单点,一旦出现问题,其他参与者将无法释放事务资源,也无法完成事务操作;

  • 数据不一致。当执行事务提交过程中,如果协调者向所有参与者发送Commit请求后,发生局部网络异常或者协调者在尚未发送完Commit请求,即出现崩溃,最终导致只有部分参与者收到、执行请求。于是整个系统将会出现数据不一致的情形;

  • 保守。2PC没有完善的容错机制,当参与者出现故障时,协调者无法快速得知这一失败,只能严格依赖超时设置来决定是否进一步的执行提交还是中断事务。

实际上分布式事务是一件非常复杂的事情,两阶段提交只是通过增加了事务协调者(Coordinator)的角色来通过2个阶段的处理流程来解决分布式系统中一个事务需要跨多个服务节点的数据一致性问题。但是从异常情况上考虑,这个流程也并不是那么的无懈可击。

假设如果在第二个阶段中Coordinator在接收到Partcipant的"Vote_Request"后挂掉了或者网络出现了异常,那么此时Partcipant节点就会一直处于本地事务挂起的状态,从而长时间地占用资源。当然这种情况只会出现在极端情况下,然而作为一套健壮的软件系统而言,异常Case的处理才是真正考验方案正确性的地方。

总结一下: XA-两阶段提交协议中会遇到的一些问题

性能问题

从流程上我们可以看得出,其最大缺点就在于它的执行过程中间,节点都处于阻塞状态。各个操作数据库的节点此时都占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知进行全局提交,参与者进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大。

协调者单点故障问题

トランザクション コーディネーターは XA モデル全体の中核であり、トランザクション コーディネーター ノードがハングアップすると、参加者は送信またはロールバックの通知を受信できなくなり、参加者ノードは常にトランザクションを完了できない中間状態になります。

メッセージの欠落によるデータの不整合

第 2 段階では、ローカル ネットワークの問題が発生し、一部のトランザクション参加者がコミット メッセージを受信する一方で、他のトランザクション参加者がコミット メッセージを受信しない場合、ノード間でデータの不整合が発生します。

6.5、3PC

研究者らは、2PC の欠点を補うために、3PC、すなわち Three-Phase Commit を提案しました。

2PC の改良版として、3PC は元の 2 段階のプロセスを CanCommit、PreCommit、do Commit の 3 段階に再分割します。

6.5.1. 詳細説明: 3 段階

ここに画像の説明を挿入します

フェーズ 1: CanCommit

ビジネスに関するお問い合わせ。コーディネーターは、トランザクションの内容を含む canCommit リクエストをすべての参加者に送信し、トランザクションの送信を実行できるかどうかを問い合わせ、応答を待ちます。各参加者はトランザクションの問い合わせに応答します
通常、参加者がトランザクションがスムーズに実行できると判断した場合は Yes が返され、そうでない場合は No が返されます。

フェーズ 2: プレコミット

このフェーズでは、コーディネーターは、前のフェーズからのフィードバックに基づいて、トランザクションの PreCommit 操作を実行するかどうかを決定します。次の 2 つの可能性があります。

トランザクションのプリコミットを実行する

プリコミットリクエストを送信します。コーディネーターはすべてのノードに PreCommit リクエストを発行し、準備フェーズに入ります。

トランザクションのプリコミット。PreCommit リクエストを受信した後、参加者はトランザクション操作を実行し、Undo ログと Redo ログをローカル トランザクション ログに書き込みます。

各参加者はトランザクション操作を正常に実行し、同時に Ack 応答の形式でコーディネーターにフィードバックを送信し、同僚は最後のコミットまたは中止の指示を待ちます。

トランザクションを中断する

参加者に参加してコーディネーターに No 応答を送信するか、タイムアウトを待つと、すべての参加者から応答を取得できない場合にコーディネーターはトランザクションを中断できます。

割り込み要求を送信します。コーディネーターは、すべての参加者に中止リクエストを送信します。

トランザクションを中断します。コーディネーターから中止リクエストを受信したか、コーディネーターからのリクエスト中にタイムアウトを待ったかに関係なく、参加者はトランザクションを中断します。

フェーズ 3: doCommit

この段階で、トランザクションは実際にコミットされますが、2 つの可能性があります。

コミットを実行する

コミットリクエストを送信します。コーディネーターがすべての参加者から Ack 応答を受信すると、プリコミット状態からコミット状態に移行し、すべての参加者に doCommit リクエストを送信します。

トランザクションがコミットされます。doCommit リクエストを受信した後、参加者は正式にトランザクション送信操作を実行し、送信操作の完了後に占有されているリソースを解放します。

トランザクション送信結果をフィードバックします。参加者はトランザクションの送信を完了した後、コーディネーターに Ack メッセージを送信します。

物事をやり遂げましょう。コーディネーターがすべての参加者から Ack メッセージを受信すると、トランザクションは完了します。

トランザクションを中断する

この段階で、通常状態のコーディネーターが参加者から No 応答を受信したか、タイムアウト期間内にフィードバック メッセージを受信しなかったと仮定すると、トランザクションは中断されます。

割り込み要求を送信します。コーディネーターは、すべての参加者に中止リクエストを送信します。

トランザクションがロールバックされました。アボート要求を受信した後、参加者はフェーズ 2 で Undo メッセージを使用してトランザクションのロールバックを実行し、ロールバックの完了後に占有されているリソースを解放します。

トランザクションのロールバック結果をフィードバックします。ロールバックの完了後、参加者はコーディネーターに Ack メッセージを送信します。

中級ビジネス。コーディネーターがすべての参加者から Ack メッセージを受信すると、トランザクションは中断されます。

6.5.2. 2PC と 3PC の違い:

3PC は、2PC によって引き起こされる参加者のブロック範囲を効果的に削減し、単一障害点の後も合意に達し続けることができますが、3PC は新たな
問題をもたらします参加者が preCommit メッセージを受信した後、ネットワークが分割されている場合、コーディネーターはその後の通信ができなくなりますこの場合、参加者はタイムアウトを待った後もトランザクションの送信を実行するため、データの不整合が発生します。

2PC と 3PC の違い:

3 フェーズ コミット プロトコルでは、コーディネーターと参加者の両方にタイムアウト メカニズムが導入され、2 フェーズ コミット プロトコルの最初のフェーズが 2 つのステップ (クエリ、リソースのロック、最後にコミット) に分割されます。3 フェーズ コミットの 3 つのフェーズは、can_commit、pre_commit、do_commit です。

ここに画像の説明を挿入します

doCommit フェーズでは、参加者がコーディネーターから doCommit または中止リクエストを時間内に受信できない場合、タイムアウトを待った後、トランザクションのコミットを続行します。(実際には、これは確率に基づいて決定する必要があります。第 3 フェーズに入ると、参加者が第 2 フェーズで PreCommit リクエストを受信したことを意味します。その後、コーディネーターが PreCommit リクエストを生成するための前提条件は、コーディネーターが PreCommit リクエストを受信することです。すべての参加者に対する CanCommit の応答は Yes です (参加者が PreCommit を受信すると、参加者は全員が実際に変更に同意したことを知っていることを意味します)。ネットワーク タイムアウトやその他の理由により、参加者はコミットまたは中止応答を受信しませんが、送信が成功する可能性が高いと信じる理由があります。)

3PC が主に解決する単一点障害の問題は次のとおりです。

2PC と比較すると、3PC は主に単一障害点の問題を解決し、ブロッキングを減らします。これは、参加者がコーディネーターから情報を時間内に受信できないと、デフォルトでコミットが実行されるためです。トランザクション リソースを保持して常にブロックされるのではなく。

ただし、このメカニズムはデータの一貫性の問題を引き起こす可能性もあります。これは、ネットワークの理由により、コーディネーターによって送信された中止応答が参加者によって時間内に受信されず、参加者がタイムアウトを待った後にコミット操作を実行するためです。これにより、中止コマンドを受信して​​ロールバックを実行した他の参加者との間でデータの不整合が生じます。

「2PC と比較した 3PC の最適化は何ですか?」
2PC と比較すると、3PC はコーディネーターと参加者の両方にタイムアウト期間が設定されていますが、2PC にはコーディネーターのみのタイムアウト メカニズムがあります。これでどんな問題が解決するのでしょうか?

この最適化ポイントは主に、参加者自体がタイムアウト後に自動的に続行するタイムアウト メカニズムを備えているため、参加者がコーディネーター ノードと長時間通信できない (コーディネーターがハングアップする) ときにリソースを解放できないという問題を回避します。ローカルコミットはリソースを解放します。このメカニズムにより、トランザクション全体のブロック時間と範囲も短縮されます。

さらに、CanCommit、PreCommit、DoCommit の 3 段階の設計により、2PC と比較して追加のバッファー段階が設定され、最終コミット段階の前にすべての参加ノードの状態が一貫していることが保証されます。

上記は 2PC と比較した 3PC の改善 (2PC の最初の 2 つの問題は比較的緩和されています) ですが、3PC はまだデータの不整合の問題を完全に解決していません。DoCommit プロセス中に参加者 A がコーディネーターからの通信を受信できない場合、参加者 A は自動的に送信されますが、送信は失敗し、他の参加者は成功するため、この時点でデータは不整合になります。

6.6. XA仕様の問題

ただし、XA 仕様は 1994 年に登場し、大規模には普及していません。

  • データのロック: トランザクションが終了する前に、一貫性を確保するためにデータ分離レベルに従ってデータがロックされます。

  • プロトコルのブロック: ローカル トランザクションはブロックされ、グローバル トランザクションがコミットまたはコールバックするまで待機します。

  • 高いパフォーマンスの損失: 主にトランザクション調整の RT コストの増加に反映されており、同時トランザクション データはロックを使用して競合およびブロックされます。

XA プロトコルは比較的単純であり、商用データベースが XA プロトコルを実装すると、分散トランザクションの使用コストは比較的低くなります。ただし、XA には致命的な欠点もあります。つまり、そのパフォーマンスが理想的ではないということです。特にトランザクション注文リンクでは、同時実行量が非常に多くなる場合が多く、XA は同時実行性の高いシナリオには対応できません。XA は現在、商用データベースでは理想的にサポートされていますが、mysql データベースでは理想的にはサポートされていません。MySQL の XA 実装では準備フェーズのログが記録されず、アクティブ データベースとスタンバイ データベースの間で切り替えを戻すと、アクティブ データベースとスタンバイ データベースの間でデータの不整合が発生します。また、多くの nosql は XA をサポートしていないため、XA のアプリケーション シナリオは非常に限られています。

実際には、それは不必要ではありません。たとえば、IBM メインフレーム上の CICS に基づく多くのクロスリソースは、XA プロトコルに基づく分散トランザクションです。実際、XA は分散トランザクション処理の標準でもありますが、システムではほとんど使用されません。インターネット. その理由は次のとおりです。

  • パフォーマンス (プロトコルのブロック、応答時間の増加、ロック時間、デッドロック)。
  • データベースのサポートの完全性 (MySQL 5.7 より前には欠陥がありました)。
  • コーディネーターは、独立した J2EE ミドルウェア (初期の重量級 Weblogic、Jboss、その後の軽量級の Amitikos、Narayana、および Bitronix) に依存しています。
  • 運用と保守は複雑であり、DBA にはこの分野の経験が不足しています。
  • すべてのリソースが XA プロトコルをサポートしているわけではありません。

正確に言うと、XA は仕様およびプロトコルです。一連のインターフェイスを定義しているだけです。ただし、XA の現在の実装のほとんどはデータベースまたは MQ であるため、XA について言及するときは、多くの場合、基盤となる分散トランザクション ソリューションを指します。リソース層。実際、一部のデータ シャーディング フレームワークやミドルウェアも XA プロトコルをサポートしており、互換性と汎用性が優れています。

6.7. 柔軟な取引の分類

電子商取引などのインターネット シナリオでは、厳格なトランザクションによりデータベースのパフォーマンスと処理能力のボトルネックが露呈しています。

柔軟なトランザクションには、基本的に使用可能な状態と柔軟な状態という 2 つの特性があります。

  • 基本的な可用性とは、分散システムに障害が発生した場合に可用性の一部が失われることが許容されることを意味します。

  • 柔軟な状態とは、システムが中間状態に存在できることを指します。この中間状態は、データベースの読み取りと書き込みの分離によるマスターとスレーブの同期遅延など、システム全体の可用性には影響しません。柔軟なトランザクションの一貫性とは、結果的な一貫性を指します。

柔軟な取引は主に補償型と通知型に分かれます。

補償事務は、TCC、佐賀、TCC、佐賀に分かれます。

通知タイプのトランザクションは、MQ トランザクション メッセージとベストエフォート通知タイプに分類されます。

補償トランザクションはすべて同期であり、通知トランザクションは非同期です。

6.8. 通知トランザクション

通知型トランザクションの主流の実装は、MQ (Message Queue) を通じて、自分のトランザクションの実行状況を他のトランザクション参加者に通知することです。MQ コンポーネントは、トランザクション参加者を効果的に分離するために導入されています。各参加者は非同期に実行できるため、通知型トランザクションはトランザクションは非同期トランザクションとも呼ばれます。

通知トランザクションは主に、データを非同期で更新する必要があり、データのリアルタイム要件が低いシナリオに適しています。

非同期保証型トランザクションとベストエフォート型通知トランザクションの2種類があります。

  • 非同期保証トランザクション: 注文とショッピング カート、受領と清算、支払と決済などの内部システムは比較的制御可能であるため、主に内部システム内のデータの最終的な一貫性を確保するのに適しています。

  • ベストエフォート型通知: 外部ネットワーク環境はより複雑で信頼できないため、主に外部システムに使用されます。そのため、ネットワーク全体でのリチャージプラットフォームやオペレーター、支払いドッキングなど、最終的なデータの一貫性を達成するために最善を尽くして通知することしかできません。システムレベルのドッキング。

ここに画像の説明を挿入します

6.9. 非同期保証トランザクション

分散トランザクションにおける同期ブロッキングによるデータ操作のパフォーマンスの低下を避けるために、一連の同期トランザクション操作をメッセージ キューに基づく非同期操作に変更することを指します。

6.9.1、MQ トランザクション メッセージ ソリューション

MQ ベースのトランザクション メッセージング ソリューションは、主に MQ のセミメッセージ メカニズムに依存して、配信されるメッセージと参加者自身のローカル トランザクションの一貫性を確保します。セミメッセージメカニズムの実装原理は、実際には、2 フェーズ提出を広範に拡張した 2PC のアイデアに基づいています。

ハーフ メッセージ: 元のキュー メッセージが実行された後のロジック。後続のローカル ロジックでエラーが発生した場合、メッセージは送信されません。合格した場合は、MQ にメッセージを送信するよう通知されます。

プロセス

ここに画像の説明を挿入します

  • トランザクション開始者は、まずハーフメッセージを MQ に送信します。
  • MQ は、メッセージが正常に送信されたことを送信者に通知します。
  • ハーフメッセージの送信に成功した後、ローカルトランザクションを実行します。
  • ローカルトランザクションの実行結果に基づいてコミットまたはロールバックを返します。
  • メッセージがロールバックの場合、MQ はメッセージを配信せずに破棄し、コミットの場合、MQ はメッセージをメッセージ サブスクライバに送信します。
  • サブスクライバはメッセージに基づいてローカル トランザクションを実行します。
  • サブスクライバーがローカル トランザクションを正常に実行すると、メッセージは MQ から消費されたものとしてマークされます。
  • ローカル トランザクションの実行中に実行側がハングアップするかタイムアウトになると、MQ サーバーはプロデューサにトランザクション ステータスの取得を継続的に要求します。
  • Consumer 側の消費成功メカニズムは MQ によって保証されます。

6.9.2. 非同期保証型トランザクションの使用例

たとえば、特定の注文が成功すると、一定量のポイントがユーザーに追加されるというビジネス ルールがあるとします。

このルールでは、注文データ ソースを管理するサービスがトランザクション イニシエーターであり、ポイント データ ソースを管理するサービスがトランザクション フォロワーです。

このプロセスから、メッセージ キューに基づいて実装されたトランザクションには次の操作があることがわかります。

  • 注文サービスは注文を作成し、ローカル トランザクションを送信します。
  • 注文サービスがメッセージを公開する
  • ポイントサービスはメッセージ受信後にポイントが加算されます。

ここに画像の説明を挿入します

全体的なプロセスは比較的単純であり、ビジネス開発のワークロードは大きくないことがわかります。

注文サービスに注文作成のロジックを書く
ポイントサービスにポイントを追加するロジックを書く
トランザクションフォームの処理がシンプルで、パフォーマンスの消費が少ないことがわかります イニシエーターとフォロワーの間のトラフィックの山と谷キューを埋めることができ、業務開発作業も同時に行うことができるため、スタンドアロントランザクションと基本的に同じ量であり、ビジネスロジックの逆処理を記述する必要がありません。

したがって、スタンドアロン トランザクションに加えて、メッセージ キューに基づいて実装されるトランザクションが最優先事項となります。

6.9.3. Alibaba RocketMQ に基づいた MQ 非同期保証型トランザクションの実装

トランザクション メッセージをサポートするサードパーティ MQ がいくつかあり、これらのメッセージ キューは、RocketMQ や ActiveMQ などのセミメッセージ メカニズムをサポートします。ただし、RabbitMQ や Kafka など、一般的に使用される一部の MQ はトランザクション メッセージをサポートしていません。

Alibaba の RocketMQ ミドルウェアを例に挙げると、その考え方はおおよそ次のとおりです。

1. プロデューサ (この例ではシステム A) は、ハーフメッセージをブローカに送信します。このハーフメッセージは、メッセージの内容が不完全であることを意味するものではありません。完全なメッセージの内容が含まれています。プロデューサ側の送信ロジックは、通常のメッセージのことです。

2.broker存储半消息,半消息存储逻辑与普通消息一致,只是属性有所不同,topic是固定的RMQ_SYS_TRANS_HALF_TOPIC,queueId也是固定为0,这个tiopic中的消息对消费者是不可见的,所以里面的消息永远不会被消费。这就保证了在半消息提交成功之前,消费者是消费不到这个半消息的

3.broker端半消息存储成功并返回后,A系统执行本地事务,并根据本地事务的执行结果来决定半消息的提交状态为提交或者回滚

4.A系统发送结束半消息的请求,并带上提交状态(提交 or 回滚)

5.broker端收到请求后,首先从RMQ_SYS_TRANS_HALF_TOPIC的queue中查出该消息,设置为完成状态。如果消息状态为提交,则把半消息从RMQ_SYS_TRANS_HALF_TOPIC队列中复制到这个消息原始topic的queue中去(之后这条消息就能被正常消费了);如果消息状态为回滚,则什么也不做。

6.producer发送的半消息结束请求是 oneway 的,也就是发送后就不管了,只靠这个是无法保证半消息一定被提交的,rocketMq提供了一个兜底方案,这个方案叫消息反查机制,Broker启动时,会启动一个TransactionalMessageCheckService 任务,该任务会定时从半消息队列中读出所有超时未完成的半消息,针对每条未完成的消息,Broker会给对应的Producer发送一个消息反查请求,根据反查结果来决定这个半消息是需要提交还是回滚,或者后面继续来反查

7.consumer(本例中指B系统)消费消息,执行本地数据变更(至于B是否能消费成功,消费失败是否重试,这属于正常消息消费需要考虑的问题)

ここに画像の説明を挿入します

在rocketMq中,不论是producer收到broker存储半消息成功返回后执行本地事务,还是broker向producer反查消息状态,都是通过回调机制完成

セミメッセージを送信するときは、コールバック クラス TransactionListener が渡されます。使用する場合は、メソッドのうち 2 つを実装する必要があります。ブローカーがセミメッセージ ストレージを正常に返した後に、executeLocalTransaction メソッドが実行され、ローカル トランザクションが実行されます。その中で、checkLocalTransaction メソッドは、ブローカーがセミメッセージ ストレージを返した後に実行され、プロデューサがライブラリ テーブルのステータスをクエリする逆チェックを開始するときに実行されます。両方のメソッドの戻り値はメッセージ ステータスであり、ブローカーに半分のメッセージを送信するかロールバックするかを指示します。

ここに画像の説明を挿入します

6.9.4. ローカルメッセージテーブルソリューション

現在の MQ コンポーネントがトランザクション メッセージをサポートしていない場合や、ビジネス側への介入を最小限に抑えたい場合があります。現時点では、「DB ローカル メッセージ テーブルに基づく」別のソリューションが必要です。

ローカル メッセージ テーブルは、もともと分散トランザクションの問題を解決するために eBay によって提案されました。これは業界で最も一般的に使用されているソリューションの 1 つであり、その中心となるアイデアは、分散トランザクションをローカル トランザクションに分割して処理することです。

ローカルメッセージテーブルプロセス
ここに画像の説明を挿入します

送信側:

  • メッセージのステータスに関する情報を記録するメッセージ テーブルが必要です。
  • ビジネス データとメッセージ テーブルは同じデータベース内にあるため、それらが同じローカル トランザクション内にあることを確認してください。ローカル トランザクションを直接利用して、ビジネス データとトランザクション メッセージをデータベースに直接書き込みます。
  • ビジネス データを処理し、ローカル トランザクションでメッセージ テーブルを書き込んだ後、メッセージを MQ メッセージ キューに書き込みます。専用のデリバリー ワーカー スレッドを使用してトランザクション メッセージを MQ に配信し、配信 ACK に基づいてトランザクション メッセージ テーブルのレコードを削除します。
  • メッセージはメッセージ コンシューマに送信され、送信に失敗した場合は再試行されます。

メッセージコンシューマ:

  • メッセージ キュー内のメッセージを処理し、独自のビジネス ロジックを完成させます。
  • ローカル トランザクションが正常に処理された場合、それは正常に処理されたことを示します。
  • ローカルトランザクション処理が失敗した場合、実行が再試行されます。
  • ビジネス レベルでの障害の場合は、ビジネス補償メッセージがメッセージ プロデューサーに送信され、ロールバックやその他の操作が通知されます。

プロデューサとコンシューマは定期的にローカル メッセージ テーブルをスキャンし、未処理のメッセージまたは失敗したメッセージを再送信します。信頼性の高い自動調整および補充ロジックがある場合、このソリューションは依然として非常に実用的です。

ローカルメッセージテーブルの長所と短所:

利点:

  • ローカル メッセージ テーブルの構築コストは比較的低く、信頼性の高いメッセージ配信を実現し、分散トランザクションの最終的な一貫性を保証します。
  • バックチェック方法を提供する必要がないため、ビジネスへの侵入がさらに軽減されます。
  • 一部のシナリオでは、注釈やその他のフォームをさらに分離に使用でき、ビジネス コードを使用せずに侵入的な実装を実現できます。

欠点:

  • ローカル メッセージ テーブルはビジネスと結合しているため、汎用にすることが難しく、独立して拡張することもできません。
  • ローカル メッセージ テーブルはデータベースに基づいており、データベースはディスク IO の読み取りと書き込みを行う必要があるため、同時実行性が高い場合にはパフォーマンスのボトルネックが発生します。

6.9.5、MQ トランザクション メッセージ VS ローカル メッセージ テーブル

彼らの共通点:

1. トランザクション メッセージはすべて MQ に依存してトランザクション通知を行うため、すべて非同期です。
2. 配信側でトランザクションメッセージが重複して配信される可能性があるため、重複配信率を低減し、よりフレンドリーなメッセージ配信と重複排除を実現するためのサポートメカニズムが必要です。
3. トランザクションメッセージの利用者は、配信の重複が避けられないため、消費重複排除設計やサービス冪等設計を行う必要があります。

2 つの違い:

MQ トランザクション メッセージ:

  • MQ はハーフメッセージ メカニズムまたは同様の機能をサポートする必要があり、繰り返し配信における重複排除処理が向上します。
  • これはビジネスにとって比較的煩雑であり、ローカル操作を成功させるための対応するチェックバック機能を提供するにはビジネス側で変更する必要があります。

DBローカルメッセージテーブル:

  • データベースはトランザクション メッセージの保存に使用されるため、MQ の要件は軽減されますが、ストレージ コストは増加します。
  • トランザクション メッセージは非同期配信を使用するため、メッセージが繰り返し配信される可能性が高くなります。

ここに画像の説明を挿入します

6.10. ベストエフォート通知

ベストエフォート型通知スキームの目的は、開始側が特定のメカニズムを使用して、受信者に業務処理結果を通知するために最善の努力を尽くすことです。

ベストエフォート型の結果整合性:

本質は、定期的な検証メカニズムを導入することで結果整合性を実現することです。これはビジネスへの負担が少なく、結果整合性に対する感度が低く、ビジネス リンクが短いシナリオに適しています。

ベストエフォート型通知トランザクションは主に外部システムに使用されます。外部ネットワーク環境はより複雑で信頼できないため、リチャージ プラットフォームとオペレーター、支払いドッキング、加盟店通知、など。プラットフォームと企業間システム間のビジネス対話シナリオ。

非同期保証型トランザクションは、注文やショッピング カート、受け取りと清算、支払いと決済などの内部システムは比較的制御可能であるため、主に内部システム内のデータの最終的な一貫性を確保するのに適しています。

ここに画像の説明を挿入します

通常のメッセージでは、ローカルトランザクションの実行とメッセージ送信の一貫性の問題を解決できません。メッセージ送信はネットワーク通信のプロセスであるため、メッセージ送信プロセスが失敗したり、タイムアウトになる場合があります。タイムアウト後、メッセージの送信は成功する場合も失敗する場合もありますが、メッセージの送信者が特定できないため、このときメッセージ送信者がトランザクションをコミットするかロールバックするかで不整合が発生する可能性があります。

したがって、通知型トランザクションの難しさは、メッセージ配信と参加者のローカル トランザクションの一貫性を確保することにあります。

コア ポイントは一貫しているため、メッセージの一貫した配信を保証するためのものです。したがって、ベスト エフォート通知トランザクションは、配信プロセスにおける非同期保証タイプと同じであるため、次の 2 つの分岐もあります。

  • MQ 自体に基づくトランザクション メッセージ スキーム

  • DBに基づくローカルトランザクションメッセージテーブルのスキーム

6.10.1、MQ トランザクション メッセージ ソリューション

ベストエフォート通知を実装するには、MQ の ACK メカニズムを使用できます。

配信前のベストエフォート通知トランザクションは非同期保証型処理と似ていますが、鍵となるのは配信後の処理です。

非同期保証タイプは内部トランザクション処理にあるため、MQ とシステムは直接接続されており、厳密な権限、セキュリティ、その他の思考設計の側面は必要ありません。ベストエフォート通知トランザクションはサードパーティ システムのドッキングにあるため、ベストエフォート通知トランザクションにはいくつかの特性があります。

  • ビジネス アクティブ パーティがビジネス処理を完了すると、ビジネス パッシブ パーティ (サードパーティ システム) に通知メッセージが送信され、メッセージが失われる可能性があります。

  • ビジネス アクティブ パーティは、増分マルチレベルの時間間隔 (5 分、10 分、30 分、1 時間、24 時間) を提供し、失敗後にパッシブ ビジネス パーティを呼び出すインターフェイスを再試行するために使用されます。N 回通知した後は、通知は行われません。アラーム + ログ + 手動介入。

  • ビジネス パッシブ パーティは、通知の繰り返しの消費を防ぐための冪等のサービス インターフェイスを提供します。

  • ビジネスのアクティブな当事者は、ビジネス データを完全に理解し、責任を果たせない場合にビジネスの受動的な当事者がビジネスのロールバックを実行するのを防ぎ、データの最終的な整合性を確保するための定期的な検証メカニズムを備えている必要があります。

ここに画像の説明を挿入します

  • ビジネス活動の能動的な当事者は、ビジネス処理を完了した後、ビジネス活動の受動的な当事者にメッセージを送信するため、メッセージは失われることが許容されます。
  • アクティブなパーティはタイムラダー通知ルールを設定し、通知が失敗した後、N 回通知がなくなるまでルールに従って通知を繰り返すことができます。
  • アクティブなパーティは、パッシブなパーティがオンデマンドで照合およびクエリを実行し、失われたビジネス メッセージを復元するための照合クエリ インターフェイスを提供します。
  • 業務活動の受け身側はデータを正常に受信すると正常に応答を返し、トランザクションを終了します。
  • 受動的当事者がタイミング戦略に従って正常に受信しない場合は、ビジネス活動の能動的当事者に問い合わせて、失われたビジネス メッセージを回復します。

特徴

  • 使用されるサービス モード: クエリ可能操作、冪等操作。
  • パッシブ パーティの処理結果は、アクティブ パーティの処理結果に影響を与えません。
  • ビジネスの結果整合性に対する時間感度が低いシステムに適用可能。
  • 企業全体のシステム間の操作、または銀行通知や販売業者通知などの企業内の比較的独立したシステム間の操作に適しています。

6.10.2. ローカルメッセージテーブルソリューション

ベストエフォート通知を実装するには、ローカル メッセージ テーブルを定期的にチェックするメカニズムを使用できます。

ここに画像の説明を挿入します

送信側:

  • メッセージのステータスに関する情報を記録するメッセージ テーブルが必要です。
  • ビジネス データとメッセージ テーブルは同じデータベース内にあるため、それらが同じローカル トランザクション内にあることを確認してください。ローカル トランザクションを直接利用して、ビジネス データとトランザクション メッセージをデータベースに直接書き込みます。
  • ビジネス データを処理し、ローカル トランザクションでメッセージ テーブルを書き込んだ後、メッセージを MQ メッセージ キューに書き込みます。専用のデリバリー ワーカー スレッドを使用してトランザクション メッセージを MQ に配信し、配信 ACK に基づいてトランザクション メッセージ テーブルのレコードを削除します。
  • メッセージはメッセージ コンシューマに送信され、送信に失敗した場合は再試行されます。
  • プロデューサはローカル メッセージ テーブルを定期的にスキャンし、未処理のメッセージまたは失敗したメッセージを再送信します。信頼性の高い自動調整および補充ロジックがある場合、このソリューションは依然として非常に実用的です。

ベストエフォート通知トランザクションはサードパーティ システムとの接続に依存するため、ベストエフォート通知トランザクションにはいくつかの特性があります。

  • ビジネス アクティブ パーティがビジネス処理を完了すると、ビジネス パッシブ パーティ (サードパーティ システム) に通知メッセージが送信され、メッセージが失われる可能性があります。

  • ビジネス アクティブ パーティは、増分マルチレベルの時間間隔 (5 分、10 分、30 分、1 時間、24 時間) を提供し、失敗後にパッシブ ビジネス パーティを呼び出すインターフェイスを再試行するために使用されます。N 回通知した後は、通知は行われません。アラーム + ログ + 手動介入。

  • ビジネス パッシブ パーティは、通知の繰り返しの消費を防ぐための冪等のサービス インターフェイスを提供します。

  • ビジネスのアクティブな当事者は、ビジネス データを完全に理解し、責任を果たせない場合にビジネスの受動的な当事者がビジネスのロールバックを実行するのを防ぎ、データの最終的な整合性を確保するための定期的な検証メカニズムを備えている必要があります。

6.10.3. ベストエフォート通知トランザクション VS 非同期保証型トランザクション

私の理解では、ベストエフォート通知トランザクションは、実際には非同期保証トランザクションに基づいて開発されたビジネス実装であり、外部ドッキングに適しています。両者の主な違いは、次のようなビジネス上の違いです。

  • 参加者の観点から見ると、ベストエフォート型通知トランザクションは、プラットフォームや企業全体のシステム間のビジネス対話に適しており、非同期保証型トランザクションは、同じネットワーク システム内の内部サービス配信により適しています。
  • メッセージ レベルから見ると、ベストエフォート通知トランザクションはアクティブにプッシュされ、データ通知を確実にするためにマルチレベルの再試行メカニズムを提供する必要があります。非同期保証トランザクションでは、メッセージ コンシューマがアクティブに消費することのみが必要です。
  • データ レベルから見ると、ベストエフォート通知トランザクションでは、データの最終的な一貫性を保証するためにデータを検証するための追加の定期的な検証メカニズムが必要ですが、非同期保証型トランザクションでは、メッセージの信頼性の高い配信を確保することのみが必要であり、データ自体を検証する必要はありません。対処する。

6.11. 通知トランザクションの問題

通知トランザクションでは、ローカル トランザクションの実行とメッセージ送信の一貫性の問題を解決できません。

メッセージ送信はネットワーク通信のプロセスであるため、メッセージ送信プロセスが失敗したり、タイムアウトになる場合があります。タイムアウトが発生すると、送信が成功する場合も送信が失敗する場合もあり、メッセージの送信者が特定できないため、このときメッセージの送信者がトランザクションをコミットするかロールバックするかで不整合が発生する可能性があります。

6.11.1. メッセージ送信の一貫性

分散システムにおけるメッセージ ミドルウェアの中核的な役割は、非同期通信、アプリケーションの分離、および同時バッファリング (トラフィック ピーク シェービングとも呼ばれます) です。分散環境では、通信をネットワーク経由で実行する必要があるため、データ伝送に不確実性が生じます。これは、CAP 理論におけるパーティションのフォールト トレランスです。

メッセージ送信の一貫性とは、メッセージを生成するビジネス アクションとメッセージ送信アクションが一致していることを意味します。つまり、ビジネス オペレーションが成功した場合、このビジネス オペレーションによって生成されたメッセージは送信される必要があり、そうでない場合、メッセージは失われます。

従来のMQキュー処理プロセスではメッセージの一貫性を実現できませんでした。したがって、一貫性を確保するためにセミメッセージ テーブルとローカル メッセージ テーブルを使用する必要があります。

6.11.2. メッセージの繰り返し送信の問題とビジネスインターフェースの冪等設計

未確認のメッセージはルールに従って再配信されます。

上記のプロセスでは、メッセージの送信が繰り返されると、業務処理インターフェイスが繰り返し呼び出されます。メッセージの消費中にメッセージが繰り返し送信される主な理由は、コンシューマーがメッセージを正常に受信して処理した後、メッセージ ミドルウェアが配信ステータスを時間内に更新しないことです。メッセージの繰り返し送信が許可されている場合、コンシューマはビジネス インターフェイスの冪等設計を実装する必要があります。

6.12. 補償の種類

ただし、メッセージに基づいて実装されたトランザクションは、次のシナリオなど、すべてのビジネス シナリオを解決できるわけではありません。注文が完了すると、同時にユーザーの現金が引き落とされます。

ここでのトランザクション開始者は注文ライブラリを管理するサービスですが、トランザクション全体が送信されたかどうかは注文サービスだけで判断することはできません。なぜなら、ユーザーがトランザクションを完了するのに十分な資金を持っていることも確認する必要があり、この情報は現金を管理するサービスです。ここでは、補償の実施に基づいたトランザクションを導入できます。そのプロセスは次のとおりです。

  • 注文データを作成しますが、ローカル トランザクションはまだ送信しません
  • 注文サービスは現金サービスにリモート呼び出しを送信して、対応する金額を差し引きます。
  • 上記の手順が成功したら、注文ライブラリのトランザクションを送信します。

上記は正常で成功したプロセスですが、異常なプロセスをロールバックする必要がある場合は、追加のリモート呼び出しが現金サービスに送信され、以前に差し引かれた金額が追加されます。

上記のプロセスは、メッセージ キューに基づくトランザクション プロセスよりも複雑で、開発作業負荷も大きくなります。

  • 注文サービスで注文を作成するためのロジックを作成する
  • 現金サービスでお金を差し引くロジックを作成する
  • 現金サービスでの報酬返還のロジックを作成する

トランザクション プロセスはメッセージ ベースの分散トランザクションよりも複雑で、関連するビジネス ロールバック手法の追加開発が必要であり、サービス間のトラフィックの山を削り、谷を埋める機能も失われていることがわかります。ただし、メッセージ ベースのトランザクションよりも少し複雑なだけなので、メッセージ キュー ベースの結果整合性トランザクションを使用できない場合は、補償ベースのトランザクション フォームの使用を優先できます。

補償モデルとは何ですか?

補償モードでは、追加の調整サービスを使用して、一貫性を確保する必要があるさまざまなビジネス サービスを調整します。調整サービスは、各ビジネス マイクロサービスを順番に呼び出します。ビジネス サービスの呼び出しが異常な場合 (ビジネス例外および技術例外を含む)、以前のすべての呼び出しは無効になります。キャンセルされました。ビジネス サービスは成功しました。

補償モードには大きく分けて TCC と Saga の 2 つのスキームがあります。

ここに画像の説明を挿入します

6.13. TCC トランザクションモデル

6.13.1. TCC トランザクション モデルとは何ですか?

TCC (Try-confirm-Cancel) の概念は、パット ヘランドによって出版された「分散トランザクションを超えた生活: 背教者の意見」というタイトルの論文に由来しています。

TCC 分散トランザクション モデルは、次の 3 つの部分で構成されます。

1. メイン ビジネス サービス: メイン ビジネス サービスは、ビジネス活動全体の開始者であり、サービスのオーケストレーターであり、ビジネス活動全体の開始と完了に責任を負います。

2. スレーブ ビジネス サービス: スレーブ ビジネス サービスは、ビジネス アクティビティ全体の参加者であり、TCC ビジネス オペレーションを提供し、準備操作 (Try)、確認操作 (confirm)、キャンセル操作 (Cancel) の 3 つのインターフェイスを実現します。メイン ビジネス サービスによって呼び出されます。
ここに画像の説明を挿入します

3. ビジネス活動マネージャー: ビジネス活動マネージャーは、TCC グローバル トランザクションのトランザクション ステータスと各スレーブ ビジネス サービスのサブトランザクション ステータスの記録と維持を含むビジネス活動全体を管理および制御し、ビジネスからのすべての確認を呼び出します。ビジネス アクティビティが送信されるときのサービス オペレーション、ビジネス アクティビティがキャンセルされるときに、すべてのスレーブ ビジネス サービスの Cancel オペレーションが呼び出されます。

TCC は、ビジネス レベルでのトランザクション定義に基づいた新しいトランザクション モデルを提案します。ロックの粒度はビジネス自体によって完全に制御されます。その目的は、複雑なビジネスにおけるテーブルやデータベースにわたる大粒度のリソース ロックの問題を解決することです。

TCCではトランザクション実行プロセスをTryと確認/キャンセルの2段階に分け、各段階のロジックをビジネスコードで制御することで長時間のトランザクションを回避し、より高いパフォーマンスを得ることができます。

6.13.2. TCC ワークフロー

TCC (Try-confirm-Cancel) 分散トランザクション モデルは、XA などの従来のモデルと比較して、分散トランザクションのサポートをリソース マネージャー (RM) に依存せず、ビジネス ロジックの分解によって分散を実現するという特徴があります。事務。

TCC モデルは、ビジネス システム内の特定のビジネス ロジックについて、外部サービスを提供する場合、ある程度の不確実性を受け入れる必要があると考えています。つまり、ビジネス ロジックの予備操作の呼び出しは一時的な操作にすぎず、主要なビジネスは行われません。それを呼び出すサービスは、その後のキャンセルの権利を保持します。メイン ビジネス サービスがグローバル トランザクションをロールバックする必要があると判断した場合、以前の一時操作のキャンセルを要求します。これは、セカンダリ ビジネス サービスのキャンセル操作に対応します。メイン ビジネス サービスがグローバル トランザクションを送信する必要があると判断した場合、以前の一時的な操作 (スレーブ ビジネス サービスの確認操作に相当) をキャンセルする権利を放棄します。すべての予備操作は最終的に確認されるかキャンセルされます。

したがって、特定のビジネス サービスに対して、TCC 分散トランザクション モデルでは、ビジネス システムが次の 3 つのビジネス ロジックを提供する必要があります。
予備操作 試行: すべてのビジネス チェックを完了し、必要なビジネス リソースを予約します。

操作の確認 確認: ビジネス ロジックは、ビジネス チェックなしで実際に実行され、Try ステージで予約されたビジネス リソースのみを使用します。したがって、Try 操作が成功する限り、確認も成功する必要があります。さらに、分散トランザクションが 1 回のみ成功することを保証するために、確認操作は冪等性を満たす必要があります。

操作のキャンセル キャンセル: 試行フェーズで予約されたビジネス リソースを解放します。同様に、キャンセル操作も冪等性を満たす必要があります。

ここに画像の説明を挿入します

TCC 分散トランザクション モデルは、次の 3 つの部分で構成されます。
ここに画像の説明を挿入します

Try フェーズ: Try インターフェイスを呼び出し、ビジネスの実行を試み、すべてのビジネス チェックを完了し、ビジネス リソースを予約します。

確認またはキャンセルフェーズ: この 2 つは相互に排他的であり、どちらか一方のみを入力できます。両方とも冪等性を満たしているため、失敗後の再試行が可能です。

動作確認:業務システムの確認と提出、業務実行の確認を行い、その他の業務チェックは行わず、Tryフェーズで確保した業務リソースのみを使用します。

キャンセル操作:業務実行エラーによりロールバックが必要な場合に業務キャンセルを実行し、予約リソースを解放します。

Try フェーズが失敗した場合はキャンセルできますが、確認フェーズとキャンセル フェーズが失敗した場合はどうなりますか?

トランザクション ログが TCC に追加されます。確認フェーズまたはキャンセル フェーズでエラーが発生した場合は、再試行が実行されるため、これら 2 つのフェーズで冪等性をサポートする必要があります。再試行が失敗した場合は、回復と処理のために手動介入が必要です。

6.13.3、TCC ビジネスケース

しかし、報酬に基づいた取引形態では、注文が完了すると、同時にユーザーの現金が引き落とされるが、取引が完了しなかったり、キャンセルされた場合、顧客はそれを確認できないなど、すべての要件を満たしているわけではありません。お金が減りました。

現時点で TCC を導入できるようになります。プロセスは次のとおりです。

  • 注文サービスが注文を作成する
  • 注文サービスは現金サービスにリモート呼び出しを送信し、顧客の現金を凍結します。
  • 注文サービスデータを送信する
  • 注文サービスは現金サービスにリモート呼び出しを送信し、顧客の凍結された現金を差し引きます。

上記は正常な処理ですが、異常な処理の場合はキャッシュサービスにリモート呼び出しリクエストを送信して凍結金額を解除する必要があります。

上記のプロセスは、補償の実装に基づくトランザクションのプロセスよりも複雑であり、開発作業負荷も大きくなります。

  • 注文サービスは注文を作成するロジックを作成します
  • 現金サービスは現金を凍結するためのロジックを作成します
  • 現金サービスは現金を差し引くロジックを作成します
  • 現金サービスは現金の凍結を解除するロジックを作成します

TCC は実際には最も複雑なケースであり、すべてのビジネス シナリオに対応できますが、パフォーマンスの考慮事項や開発の複雑さの考慮事項に関係なく、そのようなトランザクションは可能な限り回避する必要があります。

6.13.4、TCC トランザクション モデルの要件

  • クエリ可能な操作: サービス操作にはグローバルに一意の識別子があり、操作には一意で明確な時間があります。

  • 冪等操作: 複数回の呼び出しによって生成されるビジネス結果は、1 回の呼び出しによって生成される結果と同じです。1 つ目は、ビジネス操作を通じて冪等性を実現すること、2 つ目は、システムがすべてのリクエストと処理の結果をキャッシュし、最後に、繰り返しのリクエストを検出した後、自動的に前の処理結果を返すことです。

  • TCC 運用: 試行フェーズ、業務の実行を試行し、すべてのサービスの検査を完了し、一貫性を達成します。準分離を達成するために必要なビジネス リソースを確保します。確認フェーズ: 業務はチェックなしで実際に実行されます。試行フェーズで確保されたビジネス リソースのみが使用されます。確認操作は冪等性も満たす必要があります。キャンセル フェーズ: ビジネスの実行をキャンセルし、Try フェーズで予約されたビジネス リソースを解放します。キャンセル操作はべき等を満たす必要があります。TCC と 2PC (2 フェーズ コミット) プロトコルの違い: TCC は、リソース層ではなくビジネス サービス層にあります。TCC には個別の準備段階がありません。Try オペレーションには、リソース操作と準備の両方の機能があります。 TCC は、ビジネス リソースを柔軟に選択し、粒度をロックできます。TCC の開発コストは 2PC の開発コストよりも高くなります。実際、TCC も 2 段階の動作ですが、TCC は 2PC 動作と同等ではありません。

  • 補償対象業務:Doステージ:実際に業務処理が実行され、業務処理の結果が外部から見えるようになる。補償段階: フォワード業務の業績を相殺または部分的に取り消し、補償業務は冪等性を満たします。制約: 補償業務は商業的に実行可能であり、分離されていない事業​​実行結果または不完全な補償によって引き起こされるリスクとコストは制御可能です。実際、TCC の確認操作とキャンセル操作は補償操作とみなすことができます。

6.13.5. TCC トランザクション モデル VS DTP トランザクション モデル

次のように、TCC トランザクション モデルと DTP トランザクション モデルを比較します。
ここに画像の説明を挿入します

これら 2 つの写真はまったく異なって見えますが、実際には多くの場所で似ています。

  • TCC モデルのメイン ビジネス サービスは DTP モデルの AP に相当し、TCC モデルのスレーブ ビジネス サービスは DTP モデルの RM に相当します。

    • DTP モデルでは、アプリケーション AP は複数のリソース マネージャー RM でリソースを操作しますが、TCC モデルでは、メイン ビジネス サービスが複数のスレーブ ビジネス サービスでリソースを操作します。たとえば、航空券の予約の場合、Meituan アプリは主要なビジネス サービスであり、四川航空と中国東方航空は二次的なビジネス サービスであり、主要なビジネス サービスは二次的なビジネス サービスのチケット リソースを使用する必要があります。違いは、DTP モデルのリソース プロバイダーは Mysql に似たリレーショナル データベースであるのに対し、TCC モデルのリソース プロバイダーは他のビジネス サービスであることです。
  • TCC モデルでは、ビジネス サービスによって提供される try、confirm、および cancel インターフェイスは、DTP モデルの RM によって提供される prepare、commit、および rollback インターフェイスと同等です。

    • XA プロトコルでは、DTP モデルの RM が、2 フェーズ送信を実現するために TM が呼び出す準備、コミット、およびロールバック インターフェイスを提供する必要があると規定しています。

    • TCC モデルでは、スレーブ ビジネス サービスは RM と同等であり、同様の試行、確認、およびキャンセルのインターフェイスを提供します。

  • トランザクションマネージャー

    • DTP モデルと TCC モデルの両方にトランザクション マネージャーがあります。違いは次のとおりです。

    • DTP モデルでは、フェーズ 1 (準備) とフェーズ 2 (コミット、ロールバック) は両方とも TM によって呼び出されます。

    • TCC モデルでは、フェーズ 1 の try インターフェイスがメインのビジネス サービス呼び出し (緑色の矢印) であり、フェーズ 2 の (確認、キャンセル インターフェイス) がトランザクション マネージャー TM 呼び出し (赤色の矢印) です。これは、TCC 分散トランザクション モデルの 2 フェーズの非同期機能です。スレーブ ビジネス サービスの最初のフェーズが正常に実行されると、メイン ビジネス サービスが送信されて完了し、トランザクション マネージャー フレームワークが 2 番目のフェーズを非同期で実行します。各スレーブ業務サービスです。ここでは分離性と一貫性がある程度犠牲になりますが、長いトランザクションの可用性は向上します。

6.13.6. TCCと2PCの比較

実際、TCC は本質的に 2PC と似ています。

  • T は Try、2 つの C は確認とキャンセルです。

  • Try は試行を意味します。リクエスト リンクの各参加者は、Try ロジックを順番に実行します。成功した場合は、確認ロジックが実行されます。失敗した場合は、キャンセル ロジックが実行されます。

TCC と XA の 2 段階の提出は同じ目的を持っており、次の図は 2 つの提出を比較したものです。
ここに画像の説明を挿入します

ステージ 1:

  • XA では、各 RM は独自のトランザクション ブランチを送信する準備をしており、実際には、リソース更新操作 (挿入、削除、更新など) を送信する準備をしています。

  • TCC では、メイン ビジネス アクティビティは、各スレーブ ビジネス サービスによって予約されたリソースを要求 (試行) します。

ステージ 2:

  • XA は、各 RM が最初の段階で正常に準備されたかどうかに基づいて、コミットするかロールバックするかを決定します。準備が成功した場合は各トランザクション ブランチをコミットし、そうでない場合は各トランザクション ブランチをロールバックします。

  • TCCでは、第1フェーズですべてのビジネスリソースが正常に予約された場合は、各スレーブビジネスサービスを確認し、そうでない場合は、すべてのスレーブビジネスサービスのリソース予約要求をキャンセル(キャンセル)します。

TCC と 2PC の違いは次のとおりです。

  • XA は、強力な一貫性を備えたリソース レベルの分散トランザクションであり、2 フェーズの送信プロセス全体にわたって、リソース ロックは常に保持されます。データベース ロックの実装に基づいて、データベースは XA プロトコルをサポートする必要があります。トランザクション実行プロセス全体で関連データをロックする必要があるため、一般に高い同時実行パフォーマンスは低くなります。

  • TCC はビジネス レベルの分散トランザクションであり、結果整合性があり、常にリソース ロックを保持するわけではないため、パフォーマンスが向上します。しかし、これはマイクロサービスにとって非常に侵入的です。マイクロサービスの各トランザクションは、try、confirm、cancel の 3 つのメソッドを実装する必要があります。開発コストが高く、将来のメンテナンスと変更のコストも高くなります。一貫性要件を達成するには、トランザクションの試行、確認。キャンセル インターフェイスは冪等の操作を実装する必要があります。トランザクション マネージャーはトランザクション ログを記録する必要があるため、ある程度のパフォーマンスが失われ、TCC トランザクション全体の時間が長くなります。

  • TCC は、(最終的な整合性に基づいて) 高い同時実行性に耐えられる目的を達成するために、各ステップでのリソースのロックを弱めます。

具体的な手順は次のとおりです。

XA は、強い一貫性を備えたリソース レベルの分散トランザクションであり、2 フェーズ コミットのプロセス全体で、リソース ロックが常に保持されます。

XA トランザクションの 2 フェーズ コミットの内部プロセスは開発者から保護されており、開発者はこのプロセスをコード レベルで認識できません。トランザクション マネージャーの 2 フェーズ コミット プロセスでは、実際には準備からコミット/ロールバックまで常にリソースがロックされます。他の人がこれら 2 つのレコードを更新する必要がある場合は、ロックが解除されるまで待つ必要があります。

TCC は、結果整合性を備えたビジネス レベルの分散トランザクションであり、常にリソース ロックを保持するわけではありません。

TCC の 2 フェーズ サブミッションは開発者から完全に保護されているわけではありません。つまり、開発者はコード レベルから 2 フェーズ サブミッションの存在を感じることができます。try、confirm/cancel の実行中、メソッドの内部ビジネス ロジックの ACID 特性を確保するために、通常、それぞれのローカル トランザクションが開かれます。で:

1. try プロセスのローカル トランザクションは、リソース予約のビジネス ロジックの正確性を保証するためのものです。

2. 確認/キャンセルによって実行されるローカル トランザクション ロジックは、予約されたリソースを確認/キャンセルして結果整合性を確保します。これは、いわゆる補償ベースのトランザクションです。複数の独立したローカルトランザクションであるため、リソースが常にロックされるわけではありません。

さらに、ここでは、確認/キャンセルによって実行されるローカル トランザクションが補償トランザクションであると述べています。

補償は、ACID 機能をサポートする独立したローカル トランザクションであり、サービス プロバイダーに対する ACID トランザクションの影響を論理的にキャンセルするために使用されます。長時間実行されるトランザクションの場合、巨大な分散 ACID トランザクションを実装する代わりに、補償ベースのソリューションでは、各サービス コールを短いローカル ACID トランザクションとして扱い、実行後すぐに送信します。

6.13.7、TCC の使用シナリオ

TCC はいくつかのシナリオで分散トランザクションを解決できますが、問題の 1 つは、各参加者が Try、confirm、および Cancel のインターフェイスとロジックを個別に実装する必要があり、これがビジネスにとって非常に煩わしいことです。

TCC ソリューションはロールバック コードと補償コードに大きく依存しているため、最終的にはロールバック コードのロジックが複雑になり、ビジネス コードの保守が困難になります。したがって、TCC ソリューションの使用シナリオは少なくなりますが、使用シナリオも存在します。

たとえば、お金、支払い、トランザクション関連のシナリオを扱う場合、誰もが TCC スキームを使用して、すべての分散トランザクションが成功するか自動的にロールバックされることを厳密に保証し、資金の正確性を厳密に保証し、資金的には問題ありません。

ここに画像の説明を挿入します

6.14. SAGA ロングトランザクションモデル

SAGA は、キューを使用して実装された非同期補償トランザクションとして見ることができます。

6.14.1. サーガ関連の概念

1987 年、プリンストン大学のヘクター・ガルシア・モリーナとケネス・セイラムは、長期にわたるトランザクションに対処する方法についての論文を発表しました。Saga は、インターリーブ可能なサブトランザクションのコレクションに分解できる長期トランザクションです。これらの各サブトランザクションは、データベースの一貫性を維持する実際のトランザクションです。

Saga モデルは、分散トランザクションを複数のローカル トランザクションに分割します。各ローカル トランザクションには、対応する実行モジュールと補償モジュール (TCC の確認とキャンセルに対応) があります。サーガ トランザクションのいずれかのローカル トランザクションが失敗した場合、以前のトランザクションを復元できます。関連する補正メソッドを呼び出して、最終的なトランザクションの一貫性を実現します。

このような SAGA トランザクション モデルでは、ある程度の分離性と一貫性が犠牲になりますが、長時間実行されるトランザクションの可用性は向上します。

Saga モデルは 3 つの部分で構成されます。

  • LLT (Long Live Transaction): ローカル トランザクションで構成されるトランザクション チェーン。
  • ローカル トランザクション: トランザクション チェーンはサブトランザクション (ローカル トランザクション)、LLT = T1+T2+T3+…+Ti で構成されます。
  • 補償: 各ローカル トランザクション Ti には、対応する補償ワードがあります。

Saga には 2 つの実行シーケンスがあります。

  • T1、T2、T3、…、Tn

  • T1、T2、…、Tj、Cj、…、C2、C1、0 < j < n

Saga には 2 つの回復戦略があります。

  • 逆方向回復: 以前に成功したすべてのサブトランザクションを元に戻します。ローカルのサブトランザクションが失敗した場合、完了したトランザクションが補償されます。例えば、異常事態の実行順序は、T1、T2、T3、…Ti、Ci、…C3、C2、C1となります。

ここに画像の説明を挿入します

  • 前方回復: 失敗したトランザクションを再試行します。成功する必要があるシナリオに適しています。この場合、Ci は必要ありません。実行シーケンス: T1、T2、…、Tj (失敗)、Tj (再試行)、…、Ti。

もちろん、フォワード リカバリに補償トランザクションを提供する必要はありません。ビジネスでサブトランザクションが (最終的には) 常に成功する場合、または補償トランザクションの定義が難しいか不可能な場合は、フォワード リカバリの方がニーズに適しています。

補償トランザクションは理論的には失敗することはありませんが、分散世界ではサーバーがダウンしたり、ネットワークに障害が発生したり、データセンターでさえ停電が発生したりする可能性があります。この状況では何ができるでしょうか? 最後の手段は、手動介入などの代替手段を提供することです。

6.14.2. Saga の利用条件

佐賀は私たちのニーズに有望だと思われます。これは長期にわたるすべての事柄に対して実行できるでしょうか? ここにはいくつかの制限があります。

  • Saga では、トップレベルの Saga と単純なサブトランザクションの 2 レベルのネストのみが許可されます。
  • 外層では全原子性は満たされません。つまり、サガには他のサガからの部分的な結果が表示される可能性があります。
  • 各サブトランザクションは独立したアトミックな動作である必要があります
  • 私たちのビジネス シナリオでは、各ビジネス環境 (航空券の予約、レンタカー、ホテルの予約、支払いなど) は当然独立した動作であり、各トランザクションは対応するサービスのデータベースを使用してアトミックな操作を保証できます。

補償に関して考慮すべき点もあります。

  • 補償トランザクションは、セマンティックの観点からトランザクション Ti の動作を元に戻しますが、データベースを Ti が実行されたときの状態に戻すことはできない場合があります。(たとえば、トランザクションがミサイル発射をトリガーした場合、これを元に戻すことはできない場合があります)

しかし、それは私たちのビジネスにとって問題ではありません。実際、元に戻すのが難しい操作も補償される場合があります。たとえば、電子メールを送信するトランザクションは、問題を説明する別の電子メールを送信することで補償できます。

6.14.3. ACID の保証:

ACID に対する Saga の保証は TCC と同じです。

  • 原子性: 通常の状況下では保証されます。
  • 一貫性 (一貫性): ある時点では、データベース A とデータベース B のデータは一貫性要件に違反しますが、最終的には一貫性が保たれます。
  • 分離: 特定の時点で、トランザクション A はトランザクション B の部分的に送信された結果を読み取ることができます。
  • 耐久性 (耐久性) ローカル トランザクションと同様に、データはコミットされている限り保持されます。

Saga は、原子性と分離性が満たされないため、ACID 保証を提供しません。元の論文は次のように説明されています。

full atomicity is not provided. That is, sagas may view the partial results of other sagas

saga ログを通じて、saga は一貫性と耐久性を確保できます。

6.14.4. SAGAモデルの解法

SAGA モデルの中心的な考え方は、特定のソリューションを通じて分散トランザクションをローカル トランザクションに変換し、それによって問題の複雑さを軽減することです。

たとえば、DB と MQ のシナリオを例にとると、ビジネス ロジックは次のようになります。

  • DBにデータを挿入します。

  • MQ にメッセージを送信します。

上記ロジックは DB と MQ という 2 つのストレージ端末に対応するため、ローカルトランザクションだけでは解決できません。そして、SAGA モデルによれば、解決策は 2 つあります。

オプション 1: セミメッセージ モード。

RocketMQ の新しいバージョンでは、このモードがサポートされています。

まず、ハーフメッセージとは何かを理解します。簡単に言えば、メッセージにステータスを追加します。送信者が初めて MQ にメッセージを入力したとき、メッセージは確認保留状態になります。この状態では、コンシューマはメッセージを利用できません。送信者は、メッセージがコンシューマによって消費される前に、MQ ともう一度対話して、メッセージを確認保留状態から確認済み状態に変更する必要があります。確認保留状態のメッセージはセミメッセージと呼ばれます。

ハーフメッセージの完全なトランザクション ロジックは次のとおりです。

  • 半分のメッセージを MQ に送信します。

  • DBにデータを挿入します。

  • 確認メッセージを MQ に送信します。

DB 操作が 2 つの MQ 操作の間にハーフメッセージの形で挟まれていることがわかりました。2 番目のステップが失敗すると、MQ 内のメッセージは常にハーフメッセージ状態になり、コンシューマーによって消費されなくなります。

では、MQ にはハーフメッセージが常に存在していたのでしょうか? あるいは、ステップ 3 が失敗した場合はどうなるでしょうか?

上記の問題を解決するために、MQ ではスキャン機構を導入しています。つまり、MQ はすべてのハーフ メッセージを一定の間隔でスキャンし、スキャンされたハーフ メッセージのうち、長期間存在しすぎているものについて送信者に問い合わせます。クエリが確認応答を受信すると、メッセージは次のような確認ステータスに変更されます。失敗した応答を受信すると、メッセージは削除されます。

ここに画像の説明を挿入します

上で述べたように、セミメッセージ メカニズムの問題は、メッセージ ステータスをクエリするためのインターフェイスをビジネス側に提供する必要があることですが、これは依然としてビジネス側にとって非常に煩わしいものです。

解決策 2: ローカル メッセージ テーブル

DBにメッセージを格納するメッセージテーブルを追加します。次のように:

  • DBビジネステーブルにデータを挿入します。

  • DBメッセージテーブルにデータを挿入します。

  • メッセージテーブル内のメッセージをMQに非同期に送信し、ACKを受信後、メッセージテーブル内のメッセージを削除します。

ここに画像の説明を挿入します

上記のように、上記のロジックを通じて、分散トランザクションは 2 つの主要なステップに分割されます。番号 1 と 2 はローカル トランザクションを構成するため、分散トランザクションの問題は解決されます。

このソリューションでは、ビジネス エンドがメッセージ クエリ インターフェイスを提供する必要はなく、ビジネス ロジックをわずかに変更するだけで済み、煩わしさは最小限に抑えられます。

6.14.5. SAGAの場合

SAGA は、ビジネス イニシエータの最終ステータスをすぐに返す必要がないシナリオに適しています。たとえば、リクエストは送信されました。後で確認するか、通知に注意してください。

SAGA を使用して上記の補償トランザクション シナリオを書き直すと、プロセスは次のようになります。

  • 注文サービスは、最終ステータスが不明な注文レコードを作成し、トランザクションをコミットします。
  • 現金サービスは必要な金額を差し引いてトランザクションを送信します。
  • 注文サービスは注文ステータスを成功に更新し、トランザクションを送信します。

上記は成功したプロセスですが、現金サービスが金額の引き落としに失敗した場合、注文サービスの最後のステップで注文ステータスが失敗に更新されます。

ビジネス コーディングのワークロードはトランザクションの補正を少し上回るもので、次のものが含まれます。

  • 注文サービスが最初の注文を作成するためのロジック
  • 注文サービスは注文成功のロジックを確認します
  • 注文サービスが注文を確認できない場合のロジック
  • 現金サービスから現金を差し引くロジック
  • キャッシュサービス報酬リターン キャッシュロジック

ただし、補償トランザクション フォームよりもパフォーマンス上の利点があります。すべてのローカル サブトランザクションの実行中、呼び出したサブトランザクションの実行を待つ必要がないため、ロック時間が短縮されます。トランザクション プロセスが多く、長いため、パフォーマンス上の利点はさらに明白です。同時に、通信にキューを使用するため、山を切り谷を埋める効果があります。

したがって、この形式は、イニシエーターの実行の最終結果を同期的に返す必要がなく、補償が可能で、高いパフォーマンス要件があり、追加のコーディングを気にしないビジネス シナリオに適しています。

ただし、もちろん、SAGA を少し変更して、リソースを予約できる TCC に似た形式にすることもできます。

6.14.6. Saga と TCC の比較

Saga相比TCC的缺点是缺少预留动作,导致补偿动作的实现比较麻烦:Ti就是commit,比如一个业务是发送邮件,在TCC模式下,先保存草稿(Try)再发送(Confirm),撤销的话直接删除草稿(Cancel)就行了。而Saga则就直接发送邮件了(Ti),如果要撤销则得再发送一份邮件说明撤销(Ci),实现起来有一些麻烦。

如果把上面的发邮件的例子换成:A服务在完成Ti后立即发送Event到ESB(企业服务总线,可以认为是一个消息中间件),下游服务监听到这个Event做自己的一些工作然后再发送Event到ESB,如果A服务执行补偿动作Ci,那么整个补偿动作的层级就很深。

不过没有预留动作也可以认为是优点:

  • 有些业务很简单,套用TCC需要修改原来的业务逻辑,而Saga只需要添加一个补偿动作就行了。

  • TCC最少通信次数为2n,而Saga为n(n=sub-transaction的数量)。

  • 有些第三方服务没有Try接口,TCC模式实现起来就比较tricky了,而Saga则很简单。

  • 没有预留动作就意味着不必担心资源释放的问题,异常处理起来也更简单。

Saga对比TCC

Saga和TCC都是补偿型事务,他们的区别为:

劣势:

  • 无法保证隔离性;

优势:

  • 一阶段提交本地事务,无锁,高性能;
  • 事件驱动模式,参与者可异步执行,高吞吐;
  • Saga 对业务侵入较小,只需要提供一个逆向操作的Cancel即可;而TCC需要对业务进行全局性的流程改造;

6.15、总体的方案对比

属性 2PC TCC Saga 异步确保型事务 尽最大努力通知
事务一致性
复杂性
业务侵入性
使用局限性
性能
维护成本

七、seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

7.1、seata简介

Seata は、マイクロサービス アーキテクチャの下で高性能で使いやすい分散トランザクション サービスを提供することに特化したオープンソースの分散トランザクション ソリューションです。Seata はユーザーに AT、TCC、SAGA、XA トランザクション モードを提供します
Seata がオープンソース化される前は、対応する内部バージョンの Seata が Ali 経済において分散整合性ミドルウェアの役割を果たし、経済の存続を支援してきました。ダブル 11 は各 BU ビジネスを強力にサポートしました。商用製品 GTS は、Alibaba Cloud および Financial Cloud で販売されています

Seata とは: https://seata.io/zh-cn/docs/overview/what-is-seata.html

ダウンロードhttps://seata.io/zh-cn/blog/download.html

公式例https://seata.io/zh-cn/docs/user/quickstart.html

7.1.1. Seata の 3 つの主要モジュール

Seata AT は、拡張された 2 フェーズの送信実装を使用します。

Seata は 3 つのモジュールに分かれています。

  • TC: トランザクションコーディネーター。トランザクション ID の生成、トランザクションの登録、送信、ロールバックなどを担当します。

  • TM: トランザクションの開始者。トランザクションの境界を定義し、分散トランザクションの開始、送信、ロールバックを TC に通知する役割を果たします。

  • RM: リソースマネージャー。各ブランチトランザクションのリソースを管理するため、各RMはブランチトランザクションとしてTCに登録されます。

Seata の AT モードでは、TM と RM は両方とも SDK およびビジネス サービスの一部であり、それらをクライアントと考えることができます。TC は、サービスの登録と検出を通じてクライアントに自身を公開する独立したサービスです。

Seata には 3 つの主要なモジュールがあり、TM と RM は Seata クライアントとして業務システムに統合され、TC は Seata サーバーとして独立して展開されます。

7.1.2、 Seata の分散トランザクション実行プロセス

Seata における分散トランザクションの実行フローは次のとおりです。

  • TM は分散トランザクションを開始します (TM はグローバル トランザクション レコードを TC に登録します)。

  • ビジネス シナリオに従ってデータベースやサービスなどのトランザクション リソースを手配します (RM はリソースの準備状況を TC に報告します)。

  • TM は分散トランザクションを終了し、トランザクションの最初のフェーズが終了します (TM は TC に分散トランザクションをコミット/ロールバックするように通知します)。

  • TC はトランザクション情報を要約し、分散トランザクションを送信するかロールバックするかを決定します。

  • TC はすべての RM にリソースをコミット/ロールバックするように通知し、トランザクションの第 2 フェーズが終了します。

ここに画像の説明を挿入します

Seata の TC、TM、RM の 3 つの役割は XA モデルとよく似ており、次の図は XA モデルの一般的なトランザクション プロセスです。

ここに画像の説明を挿入します

X/Open DTP (分散トランザクション プロセス) モデルには、次の 3 つの役割があります。

  • AP: アプリケーション、アプリケーションプログラム。それがビジネス層です。どの操作がトランザクションに属するかは、AP によって定義されます。

- TM: トランザクション マネージャー、トランザクション マネージャー。AP トランザクション要求の受信、グローバル トランザクションの管理、トランザクション ブランチのステータスの管理、RM 処理の調整、どのオペレーションがどのグローバル トランザクションおよびトランザクション ブランチに属するかを RM に通知するなど。これは、トランザクション スケジューリング モデル全体の中核部分でもあります。

- RM: リソースマネージャー、リソースマネージャー。通常、これはデータベースですが、メッセージ キュー (JMS データ ソースなど) やファイル システムなどの他のリソース マネージャーである場合もあります。

ここに画像の説明を挿入します

7.1.3、4 分散トランザクション ソリューション

Seata には、AT モード、TCC モード、Saga モード、XA モードという 4 つの分散トランザクション ソリューションがあります。

7.2. シータATモード

Seata AT モードは、サポートされている最も古いモードです。AT モードは、自動 (ブランチ) トランザクション モードの自動ブランチ トランザクションを指します。

Seata AT モデルは、強化された 2pc モデル、または強化された XA モデルです。

一般に、AT モードは 2pc 2 フェーズ コミット プロトコルを進化させたものですが、異なる点は Seata AT モードが常にテーブルをロックするとは限らないことです。

7.2.1 Eata AT モードを使用するための前提条件

  • ネイティブ ACID トランザクションをサポートするリレーショナル データベースに基づいています。

    • たとえば、MySQL 5.1 より前のバージョンでは、デフォルトの検索エンジンは MyISAM ですが、MySQL 5.5 以降のバージョンでは、デフォルトの検索エンジンは InnoDB に変更されます。MyISAM ストレージ エンジンの特徴は、テーブル レベルのロック、トランザクション、およびフルテキスト インデックスがサポートされていないことです。したがって、MyISAM に基づくテーブルは Seata AT モードをサポートしません。
  • Java アプリケーション。JDBC 経由でデータベースにアクセスします。

7.2.2、シータATモデル図

2 フェーズ コミット プロトコルの進化:

  • フェーズ 1: ビジネス データとロールバック ログ レコードが同じローカル トランザクションで送信され、ローカル ロックと接続リソースが解放されます。

  • 第2段:

    • コミットは非同期であり、非常に迅速に完了します。
    • または、1 段階のロールバック ログによるロールバック逆補償

Seata によって定式化されたトランザクション モードでの AT の完全なモデル図:

ここに画像の説明を挿入します

7.2.3. Seata AT モードの例

比較的単純なビジネス シナリオを使用して、Seata AT モードの作業プロセスを説明してみましょう。

リチャージ事業というのは、現在、ユーザーの残高を管理するサービスと、ユーザーのポイントを管理するサービスの2つがございます。

ユーザーがリチャージすると、まずユーザーのアカウントの残高が増加し、次にユーザーのポイントが増加します。

Seata AT は 2 つのフェーズに分かれており、メイン ロジックはすべて第 1 フェーズにあり、第 2 フェーズは主にロールバックまたはログ クリーニングを実行します。

第一段階のプロセス:

最初の段階のプロセスは次のとおりです。
ここに画像の説明を挿入します

1) 残高サービスの TM が TC にグローバル トランザクションの開始を申請し、TC はグローバル トランザクション ID を返します。

2) 残高サービスがローカル ビジネスを実行する前に、RM はまず支店トランザクションを TC に登録します。

3) バランス サービスは、順番に Undo ログを生成し、ローカル トランザクションを実行し、REDO ログを生成し、最後にローカル トランザクションを直接送信します。

4) 残高サービスの RM は、取引ステータスが成功したことを TC に報告します。

5) 残高サービスはリモート呼び出しを開始し、トランザクション ID をポイント サービスに渡します。

6) ポイント サービスでは、ローカル ビジネスを実行する前に、支店取引を TC に登録します。

7) ポイント サービスは、元に戻すログを生成し、ローカル トランザクションを実行し、やり直しログを生成し、最後にローカル トランザクションを直接送信します。

8)ポイントサービスのRMは、取引ステータスが成功したことをTCに報告する。

9) ポイント サービスは、成功したリモート呼び出しを残高サービスに返します。

10) 残高サービスの TM は、グローバル トランザクションの送信/ロールバックの TC に適用されます。

ポイントサービスにはTMもありますが、使わないので無視して大丈夫です。

Spring フレームワークのアノテーション付きトランザクションを使用する場合、ローカル トランザクションがコミットされる前にリモート呼び出しが発生します。ただし、実際には、リモート呼び出しが最初に開始されるか、ローカル トランザクションが最初に送信されるかは影響しません。

第 2 段階のプロセスは次のとおりです。

第 2 段階のロジックは比較的単純です。

クライアントと TC の間には長い接続があり、それが通常のグローバル送信である場合、TC は複数の RM にローカル REDO ログと UNDO ログを非同期でクリーンアップするように通知できます。ロールバックの場合、TC は各 RM にデータをロールバックするように通知できます。

ここで疑問が生じますが、ローカルトランザクションは自分で直接投入するので、後でロールバックするにはどうすればよいでしょうか? ローカル業務の前後でUNDOログやREDOログを記録しているので、UNDOログからロールバックすることができます。

元に戻すログとやり直しログとビジネス操作は同じトランザクション内にあるため、それらは確実に同時に成功するか失敗します。

ただし、各トランザクションがローカルに送信されてからロールバックが通知されるまでの間に、このデータは他のトランザクションによって変更されている可能性があり、アンドゥログを直接使用してロールバックすると、データの不整合が発生します。

このとき、RMはREDOログを使用してデータが同一で​​あるかどうかを検証し、他のトランザクションによってデータが変更されていないかどうかを確認します。注: UNDO ログは変更前のデータであり、ロールバックに使用できます。REDO ログは変更後のデータで、ロールバックの検証に使用されます。

データが他のトランザクションによって変更されていない場合は、直接ロールバックできます。データがダーティ データである場合は、さまざまな戦略に従って処理できます。

7.2.4. 電子商取引の注文シナリオにおける Seata AT モードの適用

以下では、Seata AT モードの動作原理と電子商取引の注文シナリオの使用について説明します。

以下に示すように:
ここに画像の説明を挿入します

上の図では、コーディネーターのショッピング サービスは、最初に参加者のリポジトリ サービスを呼び出して在庫を差し引き、次に参加者の注文サービスを呼び出して注文を生成します。このビジネス フローで XA モードで Seata を使用した後のグローバル トランザクション プロセスは、次の図に示されています。
ここに画像の説明を挿入します

上の図で説明されているグローバル トランザクションの実行プロセスは次のとおりです。

1) ショッピング サービスは Seata にグローバル トランザクションを登録し、グローバル トランザクション識別子 XID を生成します。

2) repo-service.repo_db および order-service.order_db のローカル トランザクションを保留中の送信ステージまで実行します (トランザクションの内容には、repo-service.repo_db および order-service.order_db に対するクエリ操作と、各ライブラリの undo_log レコードの書き込みが含まれます)。

3) repo-service.repo_db および order-service.order_db は、ブランチ トランザクションを Seata に登録し、XID に対応するグローバル トランザクション スコープに含めます。

4) repo-service.repo_db および order-service.order_db のローカル トランザクションを送信します。

5) repo-service.repo_db、order-service.order_db はブランチ トランザクションのコミット ステータスを Seata に報告します。

6) Seata は、すべての DB ブランチ トランザクションのコミット ステータスを要約し、グローバル トランザクションをコミットするかロールバックするかを決定します。

7) Seata は repo-service.repo_db および order-service.order_db にローカル トランザクションのコミット/ロールバックを通知します。ロールバックが必要な場合は、補償方法が採用されます。

このうち、1) 2) 3) 4) 5) は第 1 段階に属し、6) 7) は第 2 段階に属します。

7.2.5. Seata のデータ分離

Seata の at モードの主な実装ロジックはデータ ソース エージェントであり、データ ソース エージェントは MySQL や Oracle などのリレーショナル トランザクション データベースに基づいて実装され、データベースに基づいた分離レベルはリード コミットされます。つまり、ローカルトランザクションのサポートはseataがatモードを実装するための必須条件であり、それはseataのatモードの利用シーンを制限することにもなります。

書き込み分離
前のワークフローから、Seata の書き込み分離レベルが世界的に排他的であることが簡単にわかります。

まず、分離を書くプロセスを理解しましょう

分支事务1-开始
| 
V 获取 本地锁
| 
V 获取 全局锁    分支事务2-开始
|               |
V 释放 本地锁     V 获取 本地锁
|               |
V 释放 全局锁     V 获取 全局锁
                |
                V 释放 本地锁
                |
                V 释放 全局锁

上に示したように、分散トランザクションのロック取得プロセスは次のとおりです。
1) 最初にローカル ロックを取得します。これにより、ローカル データはすでに変更できますが、ローカル トランザクションを送信することはできません。
2) 次に、ローカル トランザクションを送信できるかどうかグローバル ロックを取得できるかどうかによって異なります。
3) グローバル ロックを取得すると、変更できるようになります。その後、ローカル トランザクションを送信して、ローカル ロックを解放します。
4) 分散トランザクションがコミットされると、グローバル ロックが解放されます。これにより、他のトランザクションがグローバル ロックを取得し、その変更をローカル データにコミットできるようになります。

ご覧のとおり、ここで重要な点は 2 つあります:
1) ローカル ロックが取得される前に、グローバル ロックは競合されません。2
) グローバル ロックが取得される前に、ローカル ロックは送信されません。

これは、データの変更が相互に排他的であることを意味します。ダーティなデータが書き込まれることはありません。グローバル ロックは、分散変更内の書き込みデータを分離できます。

独立性を書くための原則:

  • フェーズ 1 のローカル トランザクションがコミットされる前に、最初にグローバル ロックが取得されていることを確認する必要があります。

  • グローバル ロックを取得できない場合、ローカル トランザクションを送信できません。

  • グローバル ロックの取得は一定の範囲に制限されており、範囲を超えた場合は取得が諦められ、ローカル トランザクションがロールバックされ、ローカル ロックが解放されます。

例を挙げて説明すると、次のようになります。

  • 2 つのグローバル トランザクション tx1 と tx2 は、それぞれテーブル a の m フィールドを更新します。m の初期値は 1,000 です。

tx1 が最初に開始し、ローカル トランザクションを開始し、ローカル ロックを取得して、操作 m = 1000 - 100 = 900 を更新します。ローカル トランザクションがコミットされる前に、レコードのグローバル ロックが取得され、ローカル コミットによってローカル ロックが解放されます。

tx2 以降、ローカル トランザクションが開始され、ローカル ロックが取得され、更新操作は m = 900 - 100 = 800 になります。ローカル トランザクションがコミットされる前に、レコードのグローバル ロックの取得を試みます。tx1 がグローバルにコミットされる前に、レコードのグローバル ロックは tx1 によって保持されており、tx2 は再試行してグローバル ロックを待つ必要があります。

ここに画像の説明を挿入します

tx1 の 2 フェーズ グローバル コミット。グローバル ロックを解放します。tx2 はグローバル ロックを取得し、ローカル トランザクションを送信します。

tx1 の 2 段階のグローバル ロールバックの場合、tx1 はデータのローカル ロックを再取得し、分岐のロールバックを実現するために逆補償の更新操作を実行する必要があります。

ここに画像の説明を挿入します

このとき、tx2 がローカル ロックを保持したままデータのグローバル ロックを待っていると、tx1 のブランチ ロールバックは失敗します。ブランチのロールバックは、tx2 のグローバル ロックと他のロックがタイムアウトするまで再試行され、グローバル ロックが放棄され、ローカル トランザクションがロールバックされてローカル ロックが解放され、最終的に tx1 のブランチのロールバックが成功します。

プロセス全体のグローバル ロックは tx1 の終了まで tx1 によって保持されるため、ダーティ ライトの問題は発生しません。

読み取り分離レベル

Read Committed 以上のデータベース ローカル トランザクション分離レベルに基づいて、Seata (AT モード) のデフォルトのグローバル分離レベルは Read Uncommitted です。

アプリケーションが特定のシナリオにある場合、グローバル読み取りをコミットする必要があります。現在、Seata の方法は SELECT FOR UPDATE ステートメントのプロキシを使用します。

ここに画像の説明を挿入します

SELECT FOR UPDATE ステートメントの実行にはグローバル ロックが適用されます。グローバル ロックが他のトランザクションによって保持されている場合は、ローカル ロックを解放して (SELECT FOR UPDATE ステートメントのローカル実行をロールバックし)、再試行してください。このプロセス中、クエリはブロックされ、グローバル ロックが取得されるまで、つまり、読み取られた関連データが送信されるまで返されません。

全体的なパフォーマンスを考慮して、Seata の現在のソリューションではすべての SELECT ステートメントをプロキシするのではなく、FOR UPDATE SELECT ステートメントのみをプロキシします。

7.2.6. Spring Cloud は Seata AT モードを統合します

AT モードとは、自動 (分岐) トランザクション モードを指します。AT モードを使用するための前提条件は次のとおりです。

  • ネイティブ ACID トランザクションをサポートするリレーショナル データベースに基づいています。

  • Java アプリケーション。JDBC 経由でデータベースにアクセスします。

シーターアットの使い方

1.seataフレームワークを導入し、seataの基本構成を構成し、undo_logテーブルを確立します。

2. コンシューマはグローバル トランザクション アノテーション @GlobalTransactional を導入します

3. プロデューサは、グローバル トランザクション アノテーション @GlobalTransactional を導入します。

7.3、シータ TCC モード

7.3.1 はじめに

TCC は Seata AT トランザクションと同様に 2 段階のトランザクションであり、AT トランザクションとの主な違いは次のとおりです。

TCCはビジネス規範に深刻に侵入

  • 各段階でのデータ操作は独自にコーディングする必要があり、トランザクション フレームワークが自動的に処理することはできません。

TCCのパフォーマンスが向上

  • データにグローバル ロックを追加する必要がないため、複数のトランザクションが同時にデータを操作できるようになります。

ここに画像の説明を挿入します

Eata TCC は全体として 2 段階の提出モデルです。分散グローバル トランザクション。グローバル トランザクションは、複数のブランチ トランザクションで構成されます。ブランチ トランザクションは、2 段階コミット モデルの要件を満たす必要があります。つまり、各ブランチ トランザクションには、独自の次のものがある必要があります。

  • 1 段階の準備動作
  • 2 フェーズのコミットまたはロールバックの動作
    ここに画像の説明を挿入します

2 段階の動作モードの違いに基づいて、支店トランザクションを自動 (支店) トランザクション モードと TCC (支店) トランザクション モードに分けます。

AT モード (リンク未定を参照) は、ローカル ACID トランザクションをサポートするリレーショナル データベースに基づいています。

  • 1 段階の準備動作: ローカル トランザクションでは、ビジネス データの更新と対応するロールバック ログ レコードが一緒に送信されます。

  • 第 2 段階のコミット動作: 即座に正常に終了し、ロールバック ログはバッチで自動的かつ非同期にクリーンアップされます。

  • 第 2 段階のロールバック動作: ログをロールバックすることにより、データのロールバックを完了するための補正操作が自動的に生成されます。

同様に、TCC モードは、基礎となるデータ リソースのトランザクション サポートに依存しません。

  • 1 段階の準備動作: カスタム準備ロジックを呼び出します。

  • 2 段階のコミット動作: カスタム コミット ロジックの呼び出し。

  • 2 段階のロールバック動作: カスタム ロールバック ロジックの呼び出し。

いわゆる TCC モードは、カスタマイズされたブランチ トランザクションのグローバル トランザクション管理への統合のサポートを指します。

第一段階 試してみる

アカウント サービスを例に挙げると、注文時にユーザー アカウントの金額を差し引く必要があります。
ここに画像の説明を挿入します

ユーザーが100元相当の商品を購入した場合、100元が差し引かれます。

TCC トランザクションは、まず控除額 100 元を留保するか、最初に 100 元を凍結します。

ここに画像の説明を挿入します

第二段階 確認

最初の段階を無事に終えることができれば、最終的には「控除額」のビジネス(支店取引)は必ず成功するということになります。グローバル トランザクションがコミットされると、TC は現在のブランチ トランザクションのコミットを制御します。コミットに失敗した場合、TC はコミットが成功するまで何度も試行します。

グローバル トランザクションがコミットされると、凍結された量を使用して最終的にビジネス データ操作を実装できます。
ここに画像の説明を挿入します

フェーズ2キャンセル

グローバル トランザクションがロールバックされると、凍結された量は凍結解除され、以前の状態に復元されます。TC は現在のブランチ トランザクションのロールバックを制御します。ロールバックが失敗した場合、TC はロールバックが完了するまで何度も試行します。
ここに画像の説明を挿入します

複数の同時トランザクションの場合

複数の TCC グローバル トランザクションの同時実行が許可されており、控除額を実行するときは、それぞれの金額を凍結するだけで済みます。

ここに画像の説明を挿入します

8. 面接での質問

8.1. 分散トランザクションについて理解していますか? 分散トランザクションの問題をどのように解決しますか?

Seata AT モデルと Seata TCC が生産現場で最も一般的に使用されています。

  • 強整合性モデル、Seata AT 強整合性ソリューション モデルは、主にトランザクション/注文などのコア モジュールでの強整合性のために使用されます。

  • 弱い整合性モデル。Seata TCC 弱整合性ソリューションは、通常、在庫などのエッジ モジュールに使用され、TC の調整を通じて最終整合性を確保し、ビジネスを分離することもできます。

強力な一貫性のシナリオ

これらの特に厳密なシナリオでは、強力な一貫性を確保するために Seata AT モードが使用されます。

例を準備する: データが完全に正しいことが厳密に必要なシナリオ (電子商取引取引における在庫、注文、クーポンなど) が見つかった場合は、Seata AT モデルなどの成熟したミドルウェアを使用することで質問に答えることができます。

 阿里开源了分布式事务框架seata经历过阿里生产环境大量考验的框架。  seata支持Dubbo,Spring Cloud。 

ここに画像の説明を挿入します

これは Seata AT モードであり、強力な一貫性を確保し、複数のライブラリにわたるデータ変更をサポートします。

  • 注文ライブラリ: 注文を追加

  • 商品ライブラリ: 在庫を差し引く

  • クーポン ライブラリ: クーポンを保留する

弱い整合性シナリオ

データの整合性要件が特に厳しくないシナリオ、またはサブトランザクションが別のシステムによって実行されるシナリオでは、Seata TCC を使用して弱い整合性を確保するという質問に答えることができます。

例を準備します: データの一貫性が厳密に要求されていないシナリオ、または注文ステータスを更新して支払い成功メッセージを送信する電子商取引注文支払いサービスなど、サブトランザクションが別のシステムによって実行されるシナリオ。弱い一貫性のみが必要です。確保されること。

ここに画像の説明を挿入します

Seata TCC モードは、弱い一貫性を保証し、複数のサービスおよびシステムにわたるデータ変更をサポートします。上記のシナリオでは、Seata TCC モードのトランザクションが使用されます

  • 注文サービス: 注文ステータスを変更する

  • 通知サービス: 支払いステータスの送信

最終整合性シナリオ

信頼性の高いメッセージの最終的な整合性に基づいて、各サブトランザクションは長期間非同期にすることができますが、データが失われてはなりません。非同期保証トランザクションを使用できます。

電子商取引プラットフォームの支払い結果の通知など、MQ ベースの非同期保証型トランザクションを使用できます。

  • ポイントサービス:ポイント増量

  • 会計サービス: 会計記録の生成
    ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/shuai_h/article/details/129190534
おすすめ