Pythonを使用して分散トランザクションTCCを簡単に完了する、乳母レベルのチュートリアル

Pythonを使用して分散トランザクションTCCを簡単に完了する、乳母レベルのチュートリアル

分散トランザクションとは何ですか?銀行間送金業務は、典型的な分散型トランザクションのシナリオです。 A が銀行間で B に送金する必要がある場合、2 つの銀行のデータが関係します。転送の ACID は、データベースのローカル トランザクションでは保証できず、分散トランザクションを通じてのみ解決できます。

分散トランザクションとは、トランザクション イニシエーター、リソースとリソース マネージャー、およびトランザクション コーディネーターが分散システムの異なるノードに配置されていることを意味します。上記の転送業務では、ユーザーA-100操作とユーザーB+100操作は同一ノード上に存在しません。本質的に、分散トランザクションは、分散シナリオでデータ操作が正しく実行されるように設計されています。

TCC 分散トランザクションとは何ですか? TCC は Try、Confirm、Cancel の略です。これは、2007 年に発表された「分散トランザクションを超えた生活: 背教者の意見」と題された論文の中で、パット ヘランドによって初めて提案されました。

TCC構成

TCCは3つの段階に分かれています

  • 試行フェーズ: 実行を試行し、すべてのビジネス チェックを完了し (一貫性)、必要なビジネス リソースを予約します (準分離)
  • 確認フェーズ: すべてのブランチの試行が成功した場合は、確認フェーズに進みます。 Confirmは、ビジネスチェックなしで実際にビジネスを実行し、Tryステージで予約されたビジネスリソースのみを使用します。
  • キャンセル ステージ: すべてのブランチの Try 操作のいずれかが失敗した場合、プロセスはキャンセル ステージに進みます。キャンセルは、試行フェーズで予約されたビジネス リソースを解放します。

TCC 分散トランザクションには、従来の XA 分散トランザクションと同じように、次の 3 つの役割があります。

  • AP/アプリケーションは、グローバルトランザクションを開始し、どのトランザクションブランチがグローバルトランザクションに含まれるかを定義します。
  • 支店業務のさまざまなリソースの管理を担当するRM/リソースマネージャー
  • TM/トランザクション マネージャーは、確認とキャンセルの実行、ネットワーク例外の処理など、グローバル トランザクションの正しい実行の調整を担当します。

銀行間送金に似た業務を行う場合、送金 (TransOut) と入金 (TransIn) は異なるマイクロサービスに存在します。正常に完了した TCC トランザクションの一般的なシーケンス図は次のとおりです。

TCC実践

上記の銀行間振替操作の場合、最も簡単な方法は、Try 段階で残高を調整し、Cancel 段階で逆方向に残高を調整し、Confirm 段階では何​​も操作を行わないことです。これを実行すると、A がお金をうまく引き落とすと、その金額が B に送金されず、最終的にロールバックされて、A の残高が初期値に調整されるという問題があります。この過程で、A が自分の残高が差し引かれたことに気付いたが、受取人 B が長期間その残高を受け取っていない場合、A に問題が生じます。

より良い方法は、Try 段階で A の送金金額を凍結し、Confirm 段階で実際の控除を行い、Cancel 段階で資金の凍結を解除することです。こうすることで、ユーザーが見るデータはどの段階でも明確になります。

次に、TCC取引の具体的な開発を行います。

現在 TCC で利用できるオープン ソース フレームワークは主に Java 言語であり、seata が最も代表的です。この例では Python 言語を使用し、使用される分散トランザクション フレームワークは https://github.com/yedf/dtm です。これは分散トランザクションを非常にエレガントにサポートします。 TCCの構成について詳しく説明します。

まず、ユーザー残高テーブルと凍結資金テーブルの 2 つのテーブルを作成します。テーブル作成ステートメントは次のとおりです。

  1. テーブル dtm_busi.`user_account` を作成します (
  2. `id` int ( 11 ) AUTO_INCREMENT 主キー、
  3. `user_id` int ( 11 ) NULLではない一意、
  4. `balance` 小数点( 10 , 2 ) NOT NULL デフォルト'0.00' ,
  5. `create_time` datetime DEFAULT now(),
  6. `update_time` 日時 DEFAULT now()
  7. );
  8.  
  9. テーブル dtm_busi.`user_account_trading` を作成します (
  10. `id` int ( 11 ) AUTO_INCREMENT 主キー、
  11. `user_id` int ( 11 ) NULLではない一意、
  12. `trading_balance` 小数点( 10 , 2 ) NOT NULL デフォルト'0.00' ,
  13. `create_time` datetime DEFAULT now(),
  14. `update_time` 日時 DEFAULT now()
  15. );

取引テーブルでは、trading_balance は取引される金額を記録します。

まず、資金を凍結/解凍するためのコアコードを記述します。制約balance+trading_balance >= 0 がチェックされます。制約が保持されない場合、実行は失敗します。

  1. def tcc_adjust_trading(カーソル、uid、金額):
  2. 影響を受ける = utils.sqlexec(cursor, "dtm_busi.user_account_trading を更新し、trading_balance =trading_balance + %d (user_id = %d の場合) および trading_balance + %d + (dtm_busi.user_account からバランスを選択 (id = %d の場合) >= 0" % (amount, uid, amount, uid))
  3. 影響を受ける場合== 0 :
  4. 例外が発生します( "更新エラー、残高が足りない可能性があります" )

次にバランスを調整します

  1. def tcc_adjust_balance(カーソル、uid、金額):
  2. utils.sqlexec(cursor, "dtm_busi.user_account_trading を更新し、trading_balance = trading_balance+ %d を設定します。user_id=%d" %( -amount, uid))
  3. utils.sqlexec(カーソル、 「dtm_busi.user_account を更新し、残高を balance+%d に設定し、user_id を %d にします」 %(amount, uid))

次に、具体的なTry/Confirm/Cancel処理関数を書いてみましょう。

  1. @app .post( "/api/TransOutTry" )
  2. trans_out_try() を定義します:
  3. #トランザクションと例外処理
  4. tcc_adjust_trading(c, out_uid, - 30 )
  5. 戻り: "dtm_result" : "SUCCESS" }
  6.  
  7. @app .post( "/api/TransOutConfirm" )
  8. def trans_out_confirm(): 定義:
  9. #トランザクションと例外処理
  10. tcc_adjust_balance(c, out_uid, - 30 )
  11. 戻り: "dtm_result" : "SUCCESS" }
  12.  
  13. @app .post( "/api/TransOutCancel" )
  14. trans_out_cancel() を定義します:
  15. #トランザクションと例外処理
  16. tcc_adjust_trading(c, out_uid, 30 )の書式
  17. 戻り: "dtm_result" : "SUCCESS" }
  18.  
  19. @app .post( "/api/TransInTry" )
  20. trans_in_try() を定義します:
  21. #トランザクションと例外処理
  22. tcc_adjust_trading(c, in_uid, 30 )の書式
  23. 戻り: "dtm_result" : "SUCCESS" }
  24.  
  25. @app .post( "/api/TransInConfirm" )
  26. trans_in_confirm() を定義します:
  27. #トランザクションと例外処理
  28. tcc_adjust_balance(c, in_uid, 30 )は、
  29. 戻り: "dtm_result" : "SUCCESS" }
  30.  
  31. @app .post( "/api/TransInCancel" )
  32. trans_in_cancel() を定義します:
  33. #トランザクションと例外処理
  34. tcc_adjust_trading(c, in_uid, - 30 )
  35. 戻り: "dtm_result" : "SUCCESS" }

この時点で、各サブトランザクションの処理機能は正常であり、TCCトランザクションが開かれて分岐呼び出しが行われます。

  1. @app .get( "/api/fireTcc" )
  2. fire_tcc() を定義します:
  3. # tccトランザクションを開始する
  4. gid = tcc.tcc_global_transaction(dtm、utils.gen_gid(dtm)、tcc_trans)
  5. { "gid" : gid}を返します
  6.  
  7. # tcc トランザクションの特定の処理
  8. tcc_trans(t)を定義します。
  9. req = { "amount" : 30 } # ビジネスリクエストの負荷
  10. # 転送サービスの呼び出し試行|確認|キャンセル
  11. t.call_branch(req、svc + "/TransOutTry" 、svc + "/TransOutConfirm" 、svc + "/TransOutCancel" )
  12. # 転送サービスのTry|Confirm|Cancel関数を呼び出す
  13. t.call_branch(req、svc + "/TransInTry" 、svc + "/TransInConfirm" 、svc + "/TransInCancel" )

この時点で、完全な TCC 分散トランザクションが書き込まれました。

完全な成功例を実行する場合は、dtmcli-py-sample プロジェクトの指示に従ってください。

TCC ロールバック

銀行がユーザー2に金額を振り込む準備をしているときに、ユーザー2の口座に異常を発見し、失敗を返した場合はどうなりますか?この状況をシミュレートするためにコードを変更します。

  1. @app .post( "/api/TransInTry" )
  2. trans_in_try() を定義します:
  3. #トランザクションと例外処理
  4. tcc_adjust_trading(c, in_uid, 30 )の書式
  5. 戻り値: "dtm_result" : "FAILURE" }

これはトランザクション失敗の相互作用のタイミング図です

これと成功した TCC の違いは、サブトランザクションが失敗を返すと、その後グローバル トランザクションがロールバックされ、各サブトランザクションのキャンセル操作が呼び出されて、グローバル トランザクションが完全にロールバックされるようになることです。

TCCネットワーク異常

TCC のグローバル トランザクション プロセス全体にわたって、空のロールバック、べき等性、中断など、さまざまなネットワーク例外が発生する可能性があります。 TCC の例外は SAGA や信頼性の高いメッセージングなどのトランザクション モードに似ているため、この記事では、分散トランザクションの最も古典的な 7 つのソリューションの例外処理セクションで、例外に対するすべてのソリューションについて説明します。

まとめ

この記事では、TCC の理論的知識を紹介し、通常の正常な完了と正常なロールバックを含む、TCC トランザクションの記述プロセスの完全な例を示しました。この記事を通じて読者の皆様にはTCCについて深く理解して頂けたのではないかと思います。

<<:  ZK (ZooKeeper) 分散ロック実装

>>:  クラウドへの移行を成功させる方法

推薦する

大手企業がしのぎを削るクラウドコンピューティング市場で、中小企業はいかにシェアしていくのか。

「クラウド コンピューティングが、5 人の若い有名人の結婚と、Weibo での 4 人の有名人の浮気...

政府と企業のデジタル変革を加速させるファーウェイクラウドエンタープライズデジタル変革サミットフォーラムが成功裏に開催されました

10月28日、「スマートで美しい成都都市、有望なファーウェイ成都都市サミット2020」が成功裏に開催...

​本日、China Electronics Cloud はいくつかの主要なイベントを発表しました。

6月8日、「山と海が抱く、雲と未来」をテーマにした2022年中国電子クラウドイノベーション製品発表会...

草の根ウェブマスターのウェブサイトの運営プロセスについてどう思いますか?

今日と明日の百度の調整に直面して、草の根ウェブマスターである私たちに何ができるでしょうか? 私たちに...

#11.11# MoeCloud: US cn2 gia VPS、299元/年、512Mメモリ/1コア/10gSSD/500Gトラフィック/1Gbps帯域幅

MoeCloudはダブルイレブンのプロモーションを逃しましたが、遅くてもやらないよりはましです。公式...

Sina Weibo における SEO の価値

中国ではSina WeiboなどのSNSがますます影響力を増し、FacebookのトラフィックがGo...

Hosteons: 米国西海岸のラスベガスの新しい VPS の簡単なレビュー

VPS事業のHostenは、ロサンゼルス、ニューヨーク、ジャック・ウィアーに続き、米国ネバダ州ラスベ...

SEO担当者として、自信も必要です

あなたのサイトのランキングは停滞していますか?あなたのサイトのトラフィックはいつも少ないですか?Ba...

ソフト記事2本で問い合わせコンバージョン率を9倍に高めた体験談

ソフトコンテンツマーケティングは、近年広く普及しているオンラインマーケティング手法です。しかし、著者...

SimpleNode: ダラス ストレージ VPS、月額 5 ドル、KVM/1G メモリ/1 コア/500g ハード ドライブ/1T トラフィック

SimpleNode をまだ覚えていますか?ニュージーランドに登録された会社。2000年に設立された...

hostdime - 仮想ホスト/リセラーがまもなくオフラインになります。KVM 仮想 VPS が 25% オフ

世界的に有名なフルマネージド ホスティング プロバイダーである Hostdime.com は、5 月...

クラウドネイティブ導入2年間で運用と開発で遭遇した6つの落とし穴

1運用・保守側からの教訓運用保守側の中心的な目標は、Kubernetes クラスターの安定性を確保す...

オンラインマーケティングの旅をサポートする適切な事前サイト計画

中国におけるインターネットの台頭に伴い、多くの伝統的な企業がインターネット プラットフォームに目を向...

ウェブサイト販売計画: ブランドコピーライティングスキル

ブランドとは何ですか? ブランドとは、企業とその企業が提供する商品やサービスの包括的な識別を指します...