Seata-ATはどのようにして分散トランザクションの一貫性を保証しますか

ヘッドpicture.png
著者| Chen Jianbin(funkye)github id:a364176773
出典| AlibabaCloudネイティブ公式アカウント

Seataはオープンソースの分散トランザクションソリューションです。スターは18100以上で、コミュニティは非常に活発です。マイクロサービスアーキテクチャの下で、高性能で使いやすい分散トランザクションサービスの提供に取り組んでいます。この記事では、Seata-ATを分析します。実現原理により、ユーザーはATモードをより深く理解することができます。

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

1.シータの業務の定義

Seataは、グローバルトランザクションのフレームワークを定義します。

グローバルトランザクションは、いくつかのブランチトランザクションの全体的な調整として定義されます。

  1. TMは、TCにグローバルトランザクションの開始(開始)、送信(コミット)、およびロールバック(ロールバック)を要求します。
  2. TMは、グローバルトランザクションを表すXIDをブランチトランザクションにバインドします。
  3. RMはTCに登録し、ブランチトランザクションをXIDで表されるグローバルトランザクションに関連付けます。
  4. RMはブランチトランザクションの実行結果をTCに報告します。(オプション)
  5. TCは、ブランチコミット(ブランチコミット)またはブランチロールバック(ブランチロールバック)コマンドをRMに送信します。

1.png

Seataのグローバルトランザクション処理プロセスは、次の2つの段階に分かれています。

実行段階>:ブランチトランザクションを実行し、実行結果がロールバック可能(ロールバック可能)および耐久性(耐久性)の要件を満たしていることを確認します。
完了段階>:実行段階の結果として形成された決定に従って、TMによって発行されたグローバルコミットまたはロールバック要求をTCに適用します。> TCは、ブランチトランザクションをコミットまたはロールバックに駆動するようにRMに指示します。

Seataのいわゆるトランザクションモードは、Seataグローバルトランザクションフレームワークの下で実行されるブランチトランザクションの動作モードを指します。>>正確には、>ブランチトランザクションモード>と呼ばれる必要があります

異なるトランザクションモードの違いは、ブランチトランザクションが異なる方法を使用して、グローバルトランザクションの2つのフェーズの目標を達成することです。>>つまり、次の2つの質問に答えます。

実行段階>:実行方法と、実行結果がロールバック可能で耐久性があることを確認する方法。
完了段階>:TCコマンドを受信した後、トランザクションはロールバック/コミットされます。

2.Seataトランザクションフレームワークの下で他の2フェーズトランザクションがどのように動作するか

1)TCCトランザクションモード

まず、TCCトランザクションがSeataトランザクションフレームワークにどのように統合されているかを見てみましょう。

2.png

実際、Seataのトランザクションフレームワークと非常によく似ていることがわかりますが、RMの管理が第1段階の試行実行と第2段階の確認/キャンセルである点が異なります。同じことがTMによるトランザクションの開始(開始)であり、RMはTMです。呼び出し後、第1段階のTryメソッドを実行します。呼び出しリンクが終了すると、TMは第2段階の決定をTCに通知します。このとき、TCは第2段階の実行をRMに駆動します(通知を発行し、RMは確認/キャンセルを実行します)。

2)XAトランザクションモード

3.png

図に示すように、XAモードは実際にはSeataの下部にあるXAインターフェイスを使用します。これは、第1ステージと第2ステージで自動的に処理されます。たとえば、最初の段階では、XAのRMはプロキシユーザーデータソースを介してXAConnectionを作成し、XAトランザクション(XA開始)とXA準備を開始します(この時点で、XAのすべての操作は永続化され、ダウンしている場合でも復元できます)。フェーズ中、TCはRMにXAブランチのコミット/ロールバック操作を実行するように通知します。

ATモードとは何ですか?

最初に例を見てみましょう。

1.ワンステージ

业务sql:製品セット名= 'GTS'を更新します。ここでname = 'TXC'です。

最初のステージの実行プロセスはユーザーに認識されず、ユーザー側のビジネスSQLは変更されません。ATモードの次のステージではどうなりますか?次に、簡単に話しましょう。

  • sqlとクエリを分析してフロントミラーを取得します。name= 'TXC'の製品から、id、nameを選択します。
  • ビジネスSQLを実行します。
  • クエリ実行後のデータはポストミラーとして使用されます。id= 1の製品から、id、nameを選択します。

2.第2段階

送信:トランザクション関連の情報を削除するだけです(理論的には、削除しなくても問題ありません)。

ロールバック:ロールバックのために前の画像を取り出します。

上記の簡単な例から、ATモードが自動補償トランザクションであることが実際にわかります。ATは正確に何をしますか?以下に説明する。

ATはどのようにして分散トランザクションの一貫性を保証しますか?

この写真を最初に見てください:

4.png

上の写真を見た直後に質問をされる方も多いと思いますが、実はこれは非侵入型ATモードの概略図です。まず、ユーザーはインターフェースから入力してトランザクションイニシエーターに到達します。このとき、ビジネス開発者にとって、イニシエーターエントリは単なるビジネスインターフェースです。ビジネスSQLも同様に実行され、応答メッセージは変更なしでクライアントに返されます。その背後にあるのは、ユーザーのSQLがSeataエージェントによってホストされていることです。Seata-ATモードは、すべてのユーザーのSQLを認識し、それを操作して一貫性を確保できます。

Seata-ATはどのように邪魔になりませんか?

5.jpeg

図に示すように、Seataは、アプリケーションの起動時にユーザーのDataSourceを自動的にプロキシします。JDBC操作に精通しているユーザーは、実際にはDataSourceに精通しています。DataSourceを取得すると、データソース接続をマスターし、バックグラウンドで何かを実行できます。現時点では、「小さなアクション」もユーザーには認識されません。

ビジネスリクエストが届いた後、ビジネスSQLが実行されると、SeataはユーザーのSQLを解析し、テーブルメタデータを抽出し、プレイメージを生成し、ビジネスsqlを実行して、sqlの実行後にポストイメージを保存します(ポストミラーの導入については、後で説明します) )に、行ロックが生成された後、ブランチが登録されるときに、それはTC側であるSeata-Serverに運ばれます。

これまでのところ、クライアント側の操作の第1段階は完了しており、認識も***もありません。このとき考えてみると、実際には行ロックがあることがわかりますが、この行ロックは何のためにあるのでしょうか?これは、Seata-ATが分散条件下でトランザクションの分離を保証する方法について説明する次のステップです。公式Webサイトの例を直接取り上げましょう。

1.書き込み分離

  • ワンフェーズローカルトランザクションをコミットする前に、最初にグローバルロックを取得する必要があります
  • グローバルロック取得できずローカル業務をコミットできません。
  • グローバルロックの取得は特定の範囲に制限されており、その範囲を超えると、ローカルトランザクションがロールバックされ、ローカルロックが解除されます。

説明する例を見てください:

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

tx1が最初に開始し、ローカルトランザクションを開き、ローカルロックを取得して、m = 1000-100 = 900を更新します。ローカルトランザクションがコミットされる前、レコードのグローバルロックが最初取得され、ローカルコミットが解放されてローカルロックが解放されます。tx2の後、ローカルトランザクションを開始し、ローカルロックを取得して、m = 900-100 = 800を更新します。ローカルトランザクションがコミットされる前、レコードのグローバルロックを取得してみてください。tx1がグローバルにコミットされる前、レコードのグローバルロックはtx1によって保持され、tx2は再試行してグローバルロックを待つ必要があります 

6.png

tx1 2段階のグローバルコミット、グローバルロックを解除しますtx2はグローバルロックを取得し、ローカルトランザクションコミットします。

7.png

tx1の第2段階のグローバルロールバックが実行される場合、tx1はデータのローカルロックを再取得し、逆補正更新操作を実行して、ブランチのロールバックを実現する必要があります。

このとき、tx2がまだデータのグローバルロックを待機していて、同時にローカルロックを保持している場合、tx1のブランチロールバックは失敗します。ブランチのロールバックは、tx2のグローバルロックなどのロックが期限切れになり、グローバルロックが破棄され、ローカルトランザクションがロールバックされてローカルロックが解放されるまで再試行されます。tx1のブランチロールバックは最終的に成功します。

プロセス全体のグローバルロックはtx1の終わりまでtx1によって保持されるため、ダーティ書き込みの問題は発生しません

現時点では、誰もが孤立をよりよく理解する必要があります。この時点で、最初の段階の操作のほとんどは、すべての人によく理解されていると考えられます。次に、次の段階の分析を続けます。

2.ATモードでの2段階処理

8.jpeg

上の図からわかるように、第2フェーズのコミットでは、TCは通知のみを発行します。前のフェーズで記録されたundoLogを削除し、行ロックなどの関連するトランザクション情報を削除してから、競合ロックのためにトランザクションをブロックします。スムーズに進みます。

第2段階がロールバックの場合、より多くの処理が必要になります。

9.jpeg

まず、クライアント側のTCから通知された第2段階がロールバックの場合、対応するトランザクションの取り消しログをチェックし、取り出してミラーリングし、現在のデータを比較します(SeataATは分散トランザクションをビジネスアプリケーションレベルから保護するため)。データベース内の情報がデータベースレベルで直接変更された場合、SeataATの行ロックは分離効果を持ちません。グローバルトランザクションの外部でデータ変更があった場合、それはダーティ書き込みと判断され、Seataはこのダーティ書き込みを認識できません。現時点では、ログを印刷して例外通知をトリガーし、手動による介入が必要であることをユーザーに通知することしかできません(データ入力を標準で変更することで、不正な書き込みを回避できます)。

また、ダーティライトがない場合は比較的簡単です。フロントミラーを取り出します。トランザクションはアトミックである必要があることは誰もが知っています。一緒に発生するかどうかは関係ありません。このとき、フロントミラーは発生前にデータを記録して戻ります。ローリング後、ローカルトランザクションと同様のアトミック効果を実現します。ロールバック後、元に戻すログや行ロックなどのトランザクション関連情報を削除します。第2フェーズのロールバックは終了しました。

ATモードの第1段階と第2段階の原則と考え方を紹介したので、ATはSeataの分散トランザクションフレームワークでどのように見えますか?

10.png

ATおよびその他のトランザクションモードのSeataトランザクションフレームワークでは、(他のモードの***ポイントと比較して)追加の取り消しログテーブルがありますが、それ以外は、ビジネスではほぼゼロであることがわかります。これがATモデルがSeataで広く使用されている理由です。

3.ATモードとSeataでサポートされている他の2ステージモードの違い

まず、これまでのところ、すべてのシナリオを満たすことができる分散トランザクションは存在しないことを理解する必要があります。

ATモード、TCCモード、または佐賀モードに関係なく、これらのモードは基本的に、XA仕様が特定のシナリオの要件を満たすことができないことに由来します。

現在、比較のための3つのポイントがあります。

  • データロック

ATモードはグローバルロックを使用して基本的な書き込み分離を確保します。実際にはデータもロックしますが、ロックはTC側で一元管理され、ロック解除効率が高く、ブロッキングの問題はありません。

TCCモードはロックフリーであり、ローカルトランザクションの排他ロック機能を使用してリソースを予約し、グローバルトランザクションの解決後に対応する操作を実行します。

XAモードでは、トランザクションプロセス全体が終了する前に、関連するデータがロックされ、分離レベルの定義に従って読み取りと書き込みが制限されます。

  • デッドロック(プロトコルブロッキング)

XAモードの準備(古いバージョンのデータベースでは、XA ENDが必要であり、次に<3フェーズオリジン>を準備)の後、ブランチトランザクションはブロックフェーズに入り、XAコミットまたはXAロールバックを受信する前に待機をブロックする必要があります。

ATはロックがTC側に保存されているため、ダウングレードをサポートできます。Seataにバグやその他の問題がある場合は、後続のビジネスコールチェーンに影響を与えることなく直接ダウングレードできます。

TCCにはこの問題はありません。

  • パフォーマンス

パフォーマンスの低下は、主に2つの側面から発生します。1つは、トランザクション関連の処理および調整プロセスによって単一トランザクションのRTが増加すること、もう1つは、同時トランザクションデータのロックの競合によってスループットが低下することです。実際、主な理由は、上記のプロトコルブロッキングとデータロックです。

XAモードは1つのステージでコミットされません。大規模な同時実行シナリオでは、ロックは複数のリソースパーティ(データベースなど)に格納されるため、エネルギー消費が増大します。

ATモードのロックの細かさは行レベルまで細かく(プライマリキーが必要)、すべてのトランザクションロックはTC側に保存されるため、ロック解除は効率的かつ高速です。

TCCモードは最高のパフォーマンスを発揮し、必要なRPCオーバーヘッドはわずかで2つのローカルトランザクションのパフォーマンスオーバーヘッドですが、リソース予約シナリオを満たす必要があり、ビジネスにとってより煩わしいものです(ビジネス開発者は各インターフェイスを3つに分割する必要があります)。 1回の試行、2回の確認、およびキャンセルは第2段階で使用されます)。
多くの学生は、XAとATのロックとプロトコルのブロックについて特別な理解を持っていない可能性があるため、次の図を見てください。

11.png

XAがどれであるかを推測してみてください。実際、下の図はXAです。これは、ロックの粒度が大きくなり、ロック時間が長くなり、ATトランザクションモデルよりも同時実行パフォーマンスが大幅に低下するためです。したがって、XAモードの人気は今のところそれほど高くありません。高い。

シータの最近の計画

  • コンソール

まず、コンソールは、Seataユーザーが長い間さらしてきた問題であり、視覚的なインターフェイスがないため、ユーザーはSeataの信頼性に疑問を抱き、コンソールがないため、Seataでの分散トランザクションへの手動介入の可能性が制限されます。などなど、将来的には、1.5.0バージョンでコンソールが追加され、より多くの学生が参加して一緒に構築できるようになります。

  • いかだの統合

Raft統合の理由は、ほとんどのユーザーには特に知られていない可能性があります。まず、TC側の現在のトランザクション情報が、データベース、redis、mongodb(PRフェーズ)などの外部ストレージに保存されていることを知っておく必要があります。これにより、外部ストレージがダウンしている場合にSeataが発生します。 -サーバークラスターは完全に利用できません。サーバーがクラスターにデプロイされていて、ノードが10個以上ある場合でも、この理由でサーバーを使用できなくなります。これは受け入れられません。

そのため、各Seata-Serverのトランザクション情報の一貫性を保つためにRaftが導入されています。ノードがダウンしても、トランザクション情報の正確性が損なわれることはないため、分散トランザクションの一貫性がより保証されます。(Seata-Server raftの実装は、後の新しい章で共有されます。)

  • undoLog圧縮

これは、1.5.0 ATモードの比較的大規模なパフォーマンス最適化です。操作の最初の段階でデータが大きくなるため、Seataはその背後にあるユーザーの元に戻すログ情報を挿入するため、データも大きくなり、ストレージが遅くなる可能性があります。可能であるため、UNDOログの挿入がATトランザクションにならないように、UNDOログを圧縮する必要があります。これは、ブランチデータの量が多い場合に大きな心筋オーバーヘッドになります。

総括する

最終的な分析では、ATはリソース操作を実装し、元の状態と変更された状態を記録し、ロックを使用してデータを確実に分離するエージェントです。コールチェーンで例外が発生した場合は、すべてのブランチデータを復元して、分散トランザクションで「アトミック性」を実現します。

将来はどうですか?redis、mongodb、mq?楽しみにしています。

Seataプロジェクトのコアバリューは、分散トランザクションの問題を包括的に解決するための標準化されたプラットフォームを構築することです。

Seataに基づいて、上位のアプリケーションアーキテクチャは、実際のシナリオのニーズに応じて適切な分散トランザクションソリューションを柔軟に選択できます。プロジェクトの構築に参加し、標準化された分散トランザクションプラットフォームを共同で作成することは誰でも歓迎します。

12.png

おすすめ

転載: blog.51cto.com/13778063/2575768