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) 分散ロック実装

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

推薦する

hostens-8.3 ユーロ/年払い/VPS/768M メモリ/15g ハードディスク/1T トラフィック/400M ポート

hostens.eu はつい最近設立されたばかりなので、あまり知られていない方も多いかもしれません。...

クラウドコンピューティングにおける寡占競争は続く

クラウドコンピューティングの分野では、近年、Amazon、Microsoft、Google などのテ...

キリン広告連合感謝祭プレゼント企画 ウェブマスター300名にデジタルギフトをプレゼント

お待たせして申し訳ございません!シーズン2から2年を経て、「7年目の感謝、カーニバルギフト」シーズン...

Appleは、ユーザーのプライバシーの収集に関するCCTVの質問に回答

7月11日、CCTVは「ニュースライブ」番組で、アップルの携帯電話でこのソフトウェアが使用されている...

ビジネスデータをクラウドに移行する際の技術的な考慮事項

序文JDグループ社内およびJD Cloudのお客様のJD Public Cloud、JD Priva...

hosthongkong: 香港ダイレクト VPS、月額 9.87 ドル - 512M メモリ / 1 コア / 20g ハードディスク / 200G トラフィック

Hosthongkong は 2003 年に設立され、仮想ホストとしてスタートしました。現在の主な事...

フレンドリーリンクプラットフォームは、「ウェブサイト最適化提案」のおかげで効率的なトラフィックを獲得します

ウェブサイトを構築するウェブマスターは皆、フレンドリーリンクがウェブサイトの重みを高めることができる...

全国の人々がオンラインで授業を受けたり仕事をしたりしていますが、Alibaba Cloud はトラフィックのピークにも耐えています。

「仕事は中止するがビジネスは中止しない」そして「授業は中止するが学習は中止しない」。 2月10日は学...

Baihe.comの違法研修の謎:資格のない協力機関が破産

ちょうど旧正月が過ぎたばかりだったが、ウー・スーヤンは心の中にほとんど温かさを感じていなかった。百合...

2019年のクラウドコンピューティングのレビュー:5G+AI+クラウドがトレンドになり、クラウドゲームが次のホットスポットになる可能性

2019年へのカウントダウンが始まりました。クラウド コンピューティング市場を振り返ると、変化と課題...

曽鵬慧:百度のプロモーション戦略1:マルチアカウントプロモーション

プロモーターの日常的なアカウント管理と最適化のプロセスでは、平均クリック価格、1日のPV、インプレッ...

デルテクノロジーズのグローバルCTOが2021年のテクノロジートレンドを解説

2021年初頭、主要機関は今後の技術発展の動向分析と展望を発表しました。クラウドネイティブ、ビッグデ...

サイトのアップグレード中に注意しなければならないいくつかの小さな詳細について簡単に説明します。

セキュリティやユーザーフレンドリーなエクスペリエンスなどを向上させるために、すべてのサイトは必然的に...

Vultr:「High Frequency」高性能クラウドサーバーシリーズを追加、割引コードもあります!

Vultrは本日、ハイエンドの高周波シリーズに重点を置いた新しいクラウドサーバー製品シリーズ「Hig...