Seata 号 TCC の設計と実装

著者: 劉岳才

この記事では、seata-goにおけるTCCの設計思想、例外処理、実際の使い方を中心に紹介します。

Seata はオープンソースの分散トランザクション ソリューションであり、最新のマイクロサービス アーキテクチャの下で分散トランザクションに高性能で使いやすい分散トランザクション サービスを提供することに特化しています。Seata は、AT、TCC、SAGA、XA などのさまざまなトランザクション モードをユーザーに提供し、ユーザーがさまざまなシナリオでビジネス上の問題を解決できるように支援します。同時に、Seata は多言語プログラミングもサポートしており、シンプルな API インターフェイス、豊富なドキュメント、クイックスタート サンプル サンプル プロジェクトを提供します。これらは、開発者が Seata をすぐに使い始めて使用するのにも役立ちます。

Seata-go は Seata の多言語エコシステムにおける golang 言語の実装であり、golang 開発者が Seata の機能を使用して分散トランザクション シナリオを解決できるよう支援することに特化しています。Seata-go は Seata TC の機能を再利用しており、クライアントの機能は Seata と一貫しています。現在、Seata-go は TCC モードと AT モードをサポートしていますが、XA モードはテスト中で、5 月にリリースされる予定です。サーガ モードは現在設計および計画されており、将来的には Seata のサーガ機能と一致する予定です。

この記事では主に以下の観点から Seata-go における TCC モードの設計と使用方法を紹介します。

  • シータ号TCC実施方針
  • Sata-go TCC 例外処理
  • シータ号の展望

シータ号TCC実施方針

Seata-go は TCP ネットワーク通信に getty を使用し、Seata の通信プロトコルを完全に実装します。下位層は構成センターと登録センターを実装し、dubbo、grpc、gorm などの多くのサードパーティ フレームワークへのアクセスもサポートし、より多くのフレームワークへのアクセスをサポートするためにさまざまなコミュニティと積極的に通信しています。Seata号の簡単なシステム構成図は以下のとおりです。

画像.png

まず、TCC モードの意味を簡単に確認してみましょう。TCC は、分散トランザクション スキームの実装です。2 フェーズ コミット プロトコルを採用しています。TCC の正式名は、Try-confirm-Cancel です。Try は予約されたリソース操作、確認はコミット操作、キャンセルはロールバック操作です。 。TCC の最初のフェーズでは、最初にすべてのサブトランザクションが Try オペレーションを実行するためにトリガーされます。すべてのサブトランザクションの最初のフェーズが正常に実行されると、すべてのサブトランザクションの 2 番目のフェーズがトリガーされて confirm オペレーションが実行されます。それ以外の場合は、各サブトランザクション状態の一貫性を確保するために、2 番目のフェーズでキャンセル操作が実行されます。

TCC は侵入型分散トランザクション スキームであり、試行、確認、キャンセルの 3 段階のロジックはユーザーが実装する必要があります。これを行うとコードが増えることになり、ビジネスにとって非常に煩わしいものになりますが、利点は、柔軟性が高く、ユーザーがより複雑な分散トランザクション シナリオを解決するために使用できることです。

Seata-go の TCC モードを紹介する前に、 Seata の 3 つの中心的な役割、つまり TC、TM、および RM を確認してみましょうTC はトランザクション コーディネーターであり、グローバル トランザクションの状態を維持し、ブランチ トランザクションのコミットとロールバックをトリガーする責任を負います。TM はトランザクション マネージャーで、サブトランザクションの配置とグローバル トランザクションのコミットとロールバックを担当します。 RMはリソース管理サーバーであり、MySQLデータベースの操作などのブランチトランザクション処理のためのリソースを管理します。

これら 3 つの中心的な役割を理解すると、TCC のトランザクション プロセスを大まかに理解できるようになります。トランザクション プロセスは、次のステップに大別できます。

  • TM は TC にグローバル トランザクションの開始要求を送信し、TC 側はグローバル トランザクションのステータス情報を記録します。
  • TM はすべての RM にそれぞれリクエストを送信し、RM はブランチ トランザクションを TC に登録し、Try フェーズのロジックを実行します。
  • いずれかの RM が Try フェーズの実行が失敗したことを TM に返すと、TM は「ロールバック グローバル トランザクション」要求を TC に送信します。TC はそれを受信すると、Try を実行したすべての RM にロールバック コマンドを送信し、RM がキャンセル ロジックを実行するようにトリガーします。
  • すべての RM が Try フェーズの実行が成功したことを TM に返すと、TM は「グローバル トランザクションのコミット」の要求を TC に送信します。TC はそれを受信すると、Try を実行したすべての RM に Commit コマンドを送信し、RM が Commit ロジックを実行するようにトリガーします。

ここまでで、完全な分散トランザクションが実行されました。このプロセスのフローチャートは次のとおりです。

画像

Seata-go では、ユーザーの利便性を考慮して、TCC サービスを定義する 2 つの方法が提供されています。1 つは、次のように TwoPhaseInterface インターフェイスを実装する方法です。

画像.png

もう 1 つは、タグによって TCC サービスを定義する方法です。これは比較的複雑ですが、より柔軟です。

画像.png

2 番目のタグ ソリューションは主に特殊なシナリオに対応するもので、たとえば、dubbo-go のサーバーとクライアントはタグによって定義されますが、このときタグを使用して TCC サービスを定義する必要があります。一般に、比較的単純なインターフェイスを継承する最初の方法を使用することをお勧めします。

実際の使用では、ユーザーは次のことを行うだけで済みます。

  • 独自の TCC サービスを定義するには、上記の 2 つの方法のいずれかを参照できます。
  • TCC のプロキシ メソッド NewTCCServiceProxy を呼び出して、TCC サービスをプロキシにカプセル化します。
  • 独自のサブトランザクションを配置し、分散トランザクションのエントリ メソッド WithGlobalTx メソッドに渡します。

ここに例を示すスクリーンショットがあります。詳細なサンプルについては、アドレス https://github.com/seata/seata-go-samples にある Seata-go-samples プロジェクトを参照してください

画像.png

Seata 号 TCC 例外処理

実際に TCC を使用する場合、ネットワークやビジネス コードのロジック実行時間などの要因により、次のような問題が発生する可能性があります。

  • べき等性:トランザクションの第 1 フェーズと第 2 フェーズでは、ネットワーク遅延またはその他の理由により、RM が時間内に TC または TM に応答せず、その結果、第 1 フェーズと第 2 フェーズのロジックを実行するために RM が繰り返しトリガーされました。時には、ビジネスの冪等性を考慮する必要があります。
  • 空のロールバック:ネットワーク遅延またはその他の理由により、RM は Try リクエストを受信せずにロールバック リクエストを受信したため、空のロールバックの問題が発生しました。
  • ハング:ネットワーク遅延またはその他の理由により、RM は Try リクエストを受信せずにロールバック リクエストを受信し、ロールバック リクエストを処理した後に Try リクエストを受信しました。この時点ではグローバルトランザクションが終了しているため、トランザクションで確保したリソースは解放できなくなります。

Seata-go では、ユーザーがこの問題を解決できるように 2 つのソリューションが提供されています。

最初のメソッドの原理は Seata Java の処理ロジックと同じで、tcc_fence_log トランザクション ステータス テーブルを使用して実行されます。

画像.png

ユーザーは独自のビジネス データベースにこのテーブルを作成する必要があります。RM がビジネス SQL を送信すると、同時にこのテーブルにレコードが挿入されます。これら 2 つの SQL はローカル トランザクションで完了します。このテーブルの「グローバルトランザクションID+ブランチトランザクションID」は結合主キーであるため、繰り返し実行すると失敗するため、Tryフェーズの冪等の問題は解決されます。Commit および Cancel ステージでは、最初にこのテーブル内のブランチ トランザクションのステータスがクエリされ、次に実際のロジックが実行され、最後にステータスが更新されます。これにより、コミット フェーズとキャンセル フェーズの冪等性も保証されます。

Seata-go がトランザクションの一時停止と空のロールバックの問題をどのように解決するかを見てみましょう。Rollbback リクエストが来ると、RM は tcc_fence_log テーブルをチェックし、レコードがないことがわかります (RM が Try リクエストを受信して​​いないため)。この時点で、tcc_fence_log テーブルにレコードを挿入し、ステータスをサスペンドとしてマークし、その後、ロールバック ロジックを実行せずに直接終了するため、空のロールバックの問題が回避されます。RM が後で Try リクエストを受信した場合、tcc_fence_log テーブルにレコードがすでに存在するため、トランザクション SQL は送信できずに失敗します (tcc_fence_log には主キーの競合の問題が発生します)。これにより、アンチハングの問題が回避されます。

この方法を実現するには、Seata-go が提供するプロキシ データ ソースを使用する必要があります。これらの操作はプロキシ データ ソースによって完了されます。ユーザーは、スイッチをオンにして自分の業務 SQL に注目するだけで済みます。この機能には、実現され、今後のバージョンで実行される予定です。

2 番目の方法は、ユーザーが手動で実現します。原理は上記と同様ですが、tcc_fence_logの動作ロジックはユーザー側で実装する必要があります。一般的な使用方法は以下のスクリーンショットで説明しています。詳細はサンプルコードを参照してください。

https://github.com/seata/seata-go-samples/tree/main/tcc/fence

画像

Seata-go 展望

Seata-go コミュニティは最近、国内の多くの Go 言語マイクロサービス フレームワークや ORM フレームワークの背後にある開発コミュニティとの協力に達しました。たとえば、GORM フレームワークは Sample に統合され、さらに多くの ORM フレームワークが Seata-go-Samples に統合される予定です今後のプロジェクト中。MOSN コミュニティとの連携も進んでおり、実際の Seata ベースのトランザクション メッシュの実現に向けて取り組んでいます。

Seata-go の XA モードは 5 月にリリースされ、Seata-go は TCC、XA、および AT トランザクション モードをサポートします。シータ号のフォローアップセンターは、サーガモード機能の開発です。

現在の Saga モードは、サービス オーケストレーションの順方向および逆方向のロールバック機能のみを実現しており、さらにサービス オーケストレーションにより、DAG、時間指定タスク、タスク バッチ スケジューリングを実現し、すべてのワークフロー プロセスをカバーし、Seata プラットフォームでのユーザー エクスペリエンスを向上させることができます。現在 Seata-go は Seata Java の TC に依存していますが、この作業計画によると、将来の Seata-go バージョンではより強力な TC スケジューリングの実装が必要になる可能性があります。

Seata-go コミュニティは現在急速に成長しています。オープンソースに興味のあるより多くの友人が私たちのコミュニティに参加し、Seata-go が一緒に成長できることを願っています。

{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/3874284/blog/8863949