MySQL と Golan 間の従来の分散トランザクションのための 7 つのソリューション

MySQL と Golan 間の従来の分散トランザクションのための 7 つのソリューション

序文:

ビジネスの急速な発展とビジネスの複雑性の増大に伴い、ほぼすべての企業のシステムはモノリシックから分散型、特にマイクロサービス アーキテクチャへと移行します。すると、必然的に分散トランザクションの問題に直面することになります。
この記事では、まず関連する基本理論を紹介し、次に最も古典的なトランザクション ソリューションを要約し、最後にサブトランザクションのアウトオブオーダー実行 (べき等性、空補償、および停止問題) に対するソリューションを示して、皆様と共有します。

1. 基本理論

具体的な解決策を説明する前に、まず分散トランザクションに関係する基本的な理論的知識を理解しましょう。

送金を例に挙げてみましょう。A が B に 100 元を送金する必要がある場合、A の残高は -100 元、B の残高は +100 元である必要があります。送金全体は、A-100 と B+100 が同時に成功するか、同時に失敗することを保証する必要があります。さまざまなシナリオでこの問題を解決する方法を見てみましょう。

1.1 取引

複数のステートメントをまとめて操作する機能をデータベーストランザクションと呼びます。データベース トランザクションにより、トランザクションのスコープ内のすべての操作が成功または失敗することを保証できます。

トランザクションには、原子性一致性隔離性持久性という 4 つの特性がありますこれら 4 つの特性は、ACID 特性と呼ばれることがよくあります。

  • Atomicity :トランザクション内のすべての操作は完了するか、まったく完了しないかのいずれかであり、中間段階で終了することはありません。トランザクションの実行中にエラーが発生した場合、トランザクションが実行されなかったかのように、トランザクション開始前の状態に復元されます。
  • Consistency :トランザクションの開始前およびトランザクションの終了後にデータベースの整合性が損なわれることはありません。外部キー制約やアプリケーション定義の制約などの整合性は侵害されません。
  • Isolation :複数の同時トランザクションが同時にデータを読み取り、書き込み、変更できるようにするデータベースの機能。分離により、複数のトランザクションが同時に実行されるときに、相互実行によって発生するデータの不整合を防ぐことができます。
  • Durability :トランザクションが完了すると、データへの変更は永続的になり、システムに障害が発生しても失われません。

ビジネス システムが複雑ではなく、1 つのデータベースと 1 つのサービスでデータを変更して転送を完了できる場合は、データベース トランザクションを使用して転送ビジネスが正しく完了することを確認できます。

1.2 分散トランザクション

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

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

分散環境では、分散トランザクションは、可用性、パフォーマンス、および劣化したサービスのニーズを満たすために、一貫性と分離性の要件を軽減し、一方では BASE 理論に従います(BASE 関連の理論には多くのコンテンツが含まれるため、興味のある学生は BASE 理論を参照できます)。

  • Basic Availability
  • Soft state
  • Eventual consistency

同様に、分散トランザクションも ACID 仕様に部分的に準拠しています。

  • 原子性:厳密に従う
  • 一貫性:取引完了後の一貫性は厳密に守られ、取引中の一貫性は適切に緩和される。
  • 分離:並列トランザクションは互いに影響を及ぼさない。中間トランザクションの結果が見えることにより、安全に緩和できる。
  • 粘り強さ:厳守

2. 分散トランザクションソリューション

分散トランザクション ソリューションでは、完全なACID保証を実現することは不可能であり、すべてのビジネス上の問題を解決できる完璧なソリューションは存在しません。したがって、実際のアプリケーションでは、ビジネスのさまざまな特性に応じて、最も適切な分散トランザクション ソリューションが選択されます。

2.1 2フェーズコミット/XA

XA は、 X/Open組織によって提案された分散トランザクション仕様です。XA 仕様は主に、(グローバル) トランザクション マネージャ (TM) と (ローカル) リソース マネージャ (RM) 間のインターフェイスを定義します。 mysqlなどのローカルデータベースはXAのRMの役割を果たす

XA は 2 つの段階に分かれています。

  • フェーズ 1 ( prepare ):参加しているすべての RM がトランザクションの実行を準備し、必要なリソースをロックします。参加者のreadyたら、TM に準備ができたことを報告します。
  • フェーズ 2 ( commit/rollback ):トランザクション マネージャー (TM) は、すべての参加者 (RM) の準備ができていることを確認すると、すべての参加者にcommitコマンドを送信します。

現在、 mysqloraclesqlserverpostgre

XA トランザクションは、1 つ以上のリソース マネージャー (RM)、トランザクション マネージャー (TM)、およびpplicationProgram (ApplicationProgram) で構成されます。

ここでの RM、TM、AP の 3 つの役割は、Saga や Tcc などの後続のトランザクション モードを通じて実行される、典型的な役割の区分です。

上記の転送を例にとると、正常に完了した XA トランザクションのシーケンス図は次のようになります。

いずれかの参加者prepare失敗した場合、TM はprepareを完了したすべての参加者にロールバックを通知します。

XA トランザクションの特徴は次のとおりです。

  • 理解しやすく、開発も簡単
  • リソースが長時間ロックされており、同時実行性が低い

XAgo言語、 PHPPythonJavaC#Nodeなどをさらに学びたい読者は、 DTMを参照してください。

2.2 サガ

Saga は、このデータベース ペーパーsagasで言及されているソリューションです。基本的な考え方は、長いトランザクションを複数のローカルの短いトランザクションに分割し、Saga トランザクション コーディネータによって調整することです。正常に終了した場合は、正常に完了します。ステップが失敗した場合は、逆の順序で補正操作が 1 回呼び出されます。

上記の転送を例にとると、正常に完了した SAGA トランザクションのシーケンス図は次のようになります。

Saga Cancelステージに到達すると、ビジネス ロジックでCancelが失敗することは許可されません。ネットワークまたはその他の一時的な障害により応答が成功しなかった場合、TM はCancelが正常に返されるまで再試行を続けます。

Saga トランザクションの特徴:

  • 高い同時実行性、XAトランザクションのように長時間リソースをロックする必要がない
  • 通常動作と補償動作を定義する必要があり、開発作業量はXAよりも大きい
  • 一貫性が弱い。送金の場合、ユーザー A がすでにお金を差し引いているのに、送金が失敗することがあります。

この論文のSAGA内容は、2つの回復戦略とブランチトランザクションの同時実行など、非常に広範囲にわたります。ここでの議論は、最も単純なSAGAのみを対象としています。

SAGA 、長いトランザクションや中間結果に影響されないビジネス シナリオなど、多くのシナリオに適用できます。

SAGA をさらに学習したい場合は、SAGA の成功と失敗のロールバックの例や、さまざまなネットワーク例外の処理を含む DTM を参照できます。

2.3 TCCC

TCC (Try-Confirm-Cancel) の概念は、 2007 年Pat Hellandが発表した「分散トランザクションを超えた人生: 異端者の意見」という論文で初めて提案されました。

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

  • Tryフェーズ:実行を試行し、すべてのビジネス チェックを完了し (一貫性)、必要なビジネス リソースを予約します (準分離)
  • Confirmフェーズ:ビジネス チェックなしでビジネスの実際の実行を確認します。試行フェーズで予約されたビジネス リソースのみが使用されます。 Confirm操作にはべき等設計が必要であり、 Confirmが失敗した後に再試行する必要があります。
  • Cancelステージ:実行をキャンセルし、Try ステージで予約されたビジネス リソースを解放します。 Cancelフェーズでの例外処理ソリューションは、基本的にConfirmフェーズでのソリューションと同じであり、べき等設計が必要です。

上記の送金を例にとると、通常、金額は Try で凍結されますが差し引かれず、 Confirmで差し引かれ、 Cancelで凍結解除されます。

正常に完了した TCC トランザクションのタイミング図は次のとおりです。

TCCConfirm/Cancelフェーズでは、ビジネス ロジックで失敗を返すことはできません。ネットワークまたはその他の一時的な障害により成功を返すことができない場合、TM はConfirm/Cancel成功を返すまで再試行を続けます。

TCC の特徴は次のとおりです。

  • 高い同時実行性と長期的なリソースのロックインなし。
  • 開発作業量が多く、 Try/Confirm/Cancelインターフェースを提供する必要があります。
  • 一貫性も良好で、 SAGAがお金を差し引いたのに最終的に送金が失敗するといった事態は発生しません。
  • TCC 、注文ベースのビジネスや中間状態に制約があるビジネスに適用できます。

TCCさらに勉強したい読者は、 DTMを参照してください。

2.4 ローカルメッセージテーブル

ローカル メッセージ テーブル ソリューションは、もともとebay設計者Dan Pritchettが 2008 年にACMに公開した記事で提案しました。設計の中核は、メッセージを通じて分散処理を必要とするタスクの非同期実行を保証することです。

一般的なプロセスは次のとおりです。

ローカル メッセージの書き込みとビジネス操作は、ビジネスとメッセージ送信の原子性を確保するために 1 つのトランザクションに配置されます。すべてが成功するか、すべてが失敗します。

フォールトトレランスメカニズム:

  • 残高控除トランザクションが失敗すると、後続の手順なしでトランザクションが直接ロールバックされます。
  • ラウンドロビン順序でメッセージを生成することに失敗した場合、および残高トランザクションを増やすことに失敗した場合は再試行されます。

ローカル メッセージ テーブルの機能:

  • 長いトランザクションは複数のタスクに分割するだけで簡単に使用できます。
  • プロデューサーは追加のメッセージテーブルを作成する必要がある
  • 各ローカルメッセージテーブルをポーリングする必要がある
  • コンシューマー ロジックを正常に再試行できない場合は、操作をロールバックするための追加のメカニズムが必要になります。

非同期で実行でき、後続の操作のためにロールバックする必要のないビジネスに適用可能

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

上記のローカル メッセージ テーブル ソリューションでは、プロデューサーは追加のメッセージ テーブルを作成する必要があり、ローカル メッセージ テーブルをポーリングする必要もあるため、ビジネス上の負担が大きくなります。 Alibaba のオープンソースRocketMQ 4.3以降のバージョンでは、トランザクション メッセージが正式にサポートされています。トランザクション メッセージは基本的に、 RocketMQにローカル メッセージ テーブルを配置して、プロダクション側でのメッセージ送信とローカル トランザクション実行の間の原子性問題を解決します。

トランザクションメッセージの送信と提出:

メッセージを送信(半分のメッセージ)
サーバーはメッセージを保存し、メッセージの書き込み結果に応答して、送信結果に応じてローカルトランザクションを実行します(書き込みに失敗した場合、 halfメッセージはビジネスには見えず、ローカルロジックは実行されません)
ローカルトランザクションの状態に応じてCommitまたはRollbackを実行します( Commit操作はメッセージを公開し、コンシューマーに表示されます)

通常の送信フローチャートは次のとおりです。

補償プロセス:

Commit/Rollbackのないトランザクション メッセージ ( pending状態のメッセージ) の場合、サーバーから「レビュー」が開始されます。
プロデューサーはコールバック メッセージを受信し、メッセージに対応するローカル トランザクションのステータス ( CommitまたはRollback
トランザクション メッセージ ソリューションは、ローカル メッセージ テーブル メカニズムと非常によく似ています。主な違いは、元の関連ローカル テーブル操作がリバース クエリ インターフェイスに置き換えられていることです。

トランザクション メッセージの特性は次のとおりです。

  • 長いトランザクションは複数のタスクに分割するだけでよく、使いやすいリバース クエリ インターフェイスが提供されます。
  • コンシューマー ロジックを正常に再試行できない場合は、操作をロールバックするための追加のメカニズムが必要になります。

非同期で実行でき、後続の操作のためにロールバックする必要のないビジネスに適用可能

2.6 ベストエフォート通知

通知の発信者は、特定のメカニズムを使用して、ビジネス処理の結果を受信者に通知するために最大限の努力を払います。具体的には以下が含まれます:

特定のメッセージ繰り返し通知メカニズムがあります。通知の受信者が通知を受け取っていない可能性があるため、メッセージを繰り返すための特定のメカニズムが必要です。
メッセージ校正メカニズム。最善の努力にもかかわらず受信者に通知されない場合、または受信者がメッセージを消費した後に再度消費する必要がある場合、受信者は要求を満たすために通知側にメッセージ情報を積極的に問い合わせることができます。
先ほど紹介したローカル メッセージ テーブルとトランザクション メッセージはどちらも信頼できるメッセージです。ここで紹介したベスト エフォート通知とどう違うのでしょうか。

信頼性の高いメッセージの一貫性: 通知を開始する側は、メッセージが送信され、通知を受信する側に確実に送信されるようにする必要があります。メッセージの信頼性は、主に通知を開始する側によって保証されます。

ベスト エフォート通知: 通知の発信者は、ビジネス処理の結果を通知の受信者に通知するために最善の努力を払いますが、メッセージが受信されない場合があります。この場合、通知の受信者は、ビジネス処理の結果を照会するために発信者のインターフェイスを積極的に呼び出す必要があります。通知の信頼性は、通知の受信者に依存します。

解決策としては、ベストエフォート通知には以下が必要です。

  • 通知受信者がインターフェースを通じて業務処理結果を照会できるようにインターフェースを提供する
  • メッセージ キューACKメカニズムは、通知に必要な時間ウィンドウの上限に達するまで、通知間隔を1min5min10min30min1h2h時間、 5h10hと徐々に増やしていきます。通知はもうありません

ベスト エフォート通知は、ビジネス通知タイプに適用されます。たとえば、WeChat トランザクションの結果は、ベスト エフォート通知を通じて各販売者に通知されます。コールバック通知とトランザクション クエリ インターフェイスがあります。

2.7 ATトランザクションモード

これは、Alibaba のオープンソース プロジェクト Seata のトランザクション モードであり、Ant Financial では FMT とも呼ばれます。利点は、トランザクション モードが XA モードと同様に使用されることです。ビジネス側でさまざまな補償操作を記述する必要がなく、ロールバックはフレームワークによって自動的に完了します。欠点も XA と同様で、長いロックがあり、高同時実行シナリオに対応していません。パフォーマンスの観点から見ると、AT モードは XA よりも優れていますが、ダーティ ロールバックなどの新しい問題も発生します。

3. 例外処理

分散トランザクションのあらゆるリンクで、ネットワーク障害やビジネス障害が発生する可能性があります。これらの問題に対処するには、分散トランザクションのビジネス側で、アンチエア ロールバック、べき等性、アンチハングの 3 つの機能を実装する必要があります。

3.1 異常事態

以下では、TCC トランザクションを使用してこれらの例外を説明します。

空のロールバック:

TCC リソースの Try メソッドを呼び出さずに第 2 段階の Cancel メソッドが呼び出された場合、Cancel メソッドはこれが空のロールバックであることを認識し、直接成功を返す必要があります。

その理由は、ブランチ トランザクションがサービス ダウンタイムまたはネットワーク異常にある場合、ブランチ トランザクション呼び出しは失敗として記録されるためです。このとき、Try フェーズは実行されません。障害が回復すると、分散トランザクションがロールバックされ、2 番目のフェーズの Cancel メソッドが呼び出され、空のロールバックが発生します。

べき等性:

あらゆるリクエストによってネットワーク異常や重複リクエストが発生する可能性があるため、すべての分散トランザクション ブランチでべき等性を確保する必要があります。

サスペンション:

中断とは、分散トランザクションの場合、Try インターフェイスの前に第 2 段階のCancelインターフェイスが実行されることを意味します。

その理由は、RPC が分岐トランザクション try を呼び出すと、まず分岐トランザクションが登録され、その後 RPC 呼び出しが実行されるためです。このとき、RPC 呼び出しのネットワークが混雑していると、RPC がタイムアウトした後、TM は RM に分散トランザクションをロールバックするように通知します。ロールバックが完了した後、Try の RPC 要求が参加者に到達して実際に実行される可能性があります。

上記の問題をよりよく理解するために、ネットワーク異常のタイミング図を見てみましょう。

  • ビジネスプロセスリクエスト4では、Tryの前にCancelが実行され、空のロールバックを処理する必要がある。
  • ビジネスプロセスが6をリクエストすると、 Cancelが繰り返し実行されるため、冪等性が要求されます。
  • ビジネスプロセスリクエスト8では、 Cancel後にTryが実行され、中断を処理する必要がある。

上記の複雑なネットワーク異常に対して、現在さまざまな企業が推奨している解決策は、ビジネス側が固有のキーを使用して関連する操作が完了したかどうかを照会し、完了した場合は直接成功を返すというものです。関連する判断ロジックは複雑で、エラーが発生しやすく、大きな業務負担を課します。

3.2 サブトランザクションバリア

プロジェクト https://github.com/yedf/dtm では、サブトランザクションバリア技術が登場しました。この技術を使用すると、この効果を実現できます。概略図をご覧ください。

これらのリクエストはすべて、サブトランザクション バリアに到達すると、異常な場合はフィルタリングされ、正常な場合はバリアを通過します。開発者がサブトランザクションバリアを使用すると、上記の例外はすべて適切に処理されます。ビジネス開発者は実際のビジネスロジックに集中するだけでよくなり、負担が大幅に軽減されます。

サブトランザクション バリアは、ThroughBarrierCall と呼ばれるメソッドを提供します。そのプロトタイプは次のとおりです。

関数 ThroughBarrierCall(db *sql.DB、transInfo *TransInfo、busiCall BusiFunc)

ビジネス開発者は、busiCall に独自の関連ロジックを記述し、この関数を呼び出します。 ThroughBarrierCall 、空のロールバックや中断などのシナリオでbusiCallが呼び出されないようにします。ビジネスが繰り返し呼び出される場合は、1 回だけ送信されるようにするべき等制御が行われます。

サブトランザクションバリアはTCC、SAGA、トランザクションメッセージなどを管理し、他の領域にも拡張できます。

3.3 サブトランザクションバリア原則

サブトランザクションバリア技術の原理は、ローカルデータベースにブランチトランザクションステータステーブルsub_trans_barrier確立し、一意のキーをグローバルトランザクションID-サブトランザクションID-サブトランザクションブランチ名( try|confirm|cancel )に設定することです。

  • 取引を開く
  • Try ブランチの場合は、 insert ignore gid-branchid-tryを挿入します。挿入が成功すると、バリア内のロジックが呼び出されます。
  • Confirm ブランチの場合、 insert ignore gid-branchid-confirmを挿入します。挿入が成功すると、バリア内のロジックが呼び出されます。
  • キャンセルブランチの場合、 insert ignore gid-branchid-tryを挿入し、次にgid-branchid-cancelを挿入します。tryが挿入されず、cancelが正常に挿入された場合、バリア内のロジックが呼び出されます。
  • バリア内のロジックは成功を返し、トランザクションはコミットされ、成功が返されます
  • バリア内のロジックはエラーを返し、トランザクションをロールバックし、エラーを返します。

このメカニズムにより、ネットワーク異常に関連する問題が解決される

  • 空の補償制御 - Try が実行されず、Cancel が直接実行される場合、バリア内のロジックを経由せずに、 Cancelgid-branchid-tryに挿入することが成功し、空の補償制御が保証されます。
  • 冪等性制御 - どのブランチも一意のキーを繰り返し挿入することができず、繰り返し実行されないことを保証します。
  • ハング防止制御 - キャンセル後にトライが実行されるため、挿入されたgid-branchid-tryが失敗した場合は実行されず、ハング防止制御が保証されます。

SAGA、トランザクションメッセージなどの場合もメカニズムは同様です。

3.4 サブトランザクションバリアの概要

サブトランザクションバリアテクノロジーは、https://github.com/yedf/dtm によって最初に作成されました。その重要性は、シンプルで実装しやすいアルゴリズムを設計し、シンプルで使いやすいインターフェースを提供することにあります。これら 2 つの要素の助けにより、開発者はネットワーク例外の処理から完全に解放されます。

このテクノロジーは現在、yedf/dtm トランザクション マネージャーで使用する必要があります。SDK は現在、Go 言語と Python 言語の開発者が利用できます。他の言語向けのSDKも計画中です。他の分散トランザクション フレームワークの場合、適切な分散トランザクション情報が提供されていれば、上記の原則に従ってテクノロジを迅速に実装できます。

4. 分散トランザクションの実践

先ほど紹介した SAGA トランザクションを例に、特定の分散トランザクションを完了するためのトランザクション フレームワークとして DTM を使用します。この例では Go 言語を使用します。これに興味がない場合は、記事の最後の概要に直接ジャンプできます。

4.1 SAGAトランザクション

まずはユーザーの口座残高を調整するためのコアビジネスコードを書いてみましょう

func qsAdjustBalance(uid int, amount int) (interface{}, error) {
    _, err := dtmcli.SdbExec(sdbGet(), "dtm_busi.user_account を更新し、balance を balance + ? に設定し、user_id を ? に設定、amount、uid)
    dtmcli.ResultSuccess、err を返します
}


次に、具体的な順方向演算・補正演算処理関数を書いてみます。

    app.POST(qsBusiAPI+"/TransIn", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
        qsAdjustBalance(2, 30)を返す
    }))
    app.POST(qsBusiAPI+"/TransInCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
        qsAdjustBalance(2, -30) を返す
    }))
    app.POST(qsBusiAPI+"/TransOut", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
        qsAdjustBalance(1, -30) を返す
    }))
    app.POST(qsBusiAPI+"/TransOutCompensate", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
        qsAdjustBalance(1, 30)を返す
    }))

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

    req := &gin.H{"amount": 30} // マイクロサービス ペイロード // DtmServer は DTM サービスのアドレスです saga := dtmcli.NewSaga(DtmServer, dtmcli.MustGenGid(DtmServer)).
        // TransOut サブトランザクションを追加します。転送操作は url: qsBusi+"/TransOut"、逆操作は url: qsBusi+"/TransOutCompensate" です。
        (qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req)を追加します。
        // TransIn サブトランザクションを追加します。順方向操作は url: qsBusi+"/TransOut"、逆方向操作は url: qsBusi+"/TransInCompensate" です。
        追加(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req)
    // saga トランザクションを送信します。dtm はすべてのサブトランザクションを完了し、すべてのサブトランザクションをロールバックします。err := saga.Submit()

この時点で、完全な SAGA 分散トランザクションが記述されました。

成功した例全体を実行したい場合は、yedf/dtm プロジェクトの指示に従って環境を設定し、次のコマンドで saga の例を実行します。

go run app/main.go quick_start

4.2 ネットワーク異常の処理

dtm に送信されたトランザクションで転送操作を呼び出すときに短時間の障害が発生した場合はどうすればよいですか? SAGA トランザクション プロトコルによれば、dtm は未完了の操作を再試行します。このとき、何をすればよいでしょうか?障害は、転送操作の完了後にネットワーク障害が発生したか、転送操作中にマシンがクラッシュした可能性があります。口座残高の調整が正しいことをどのように確認すればよいでしょうか?

サブトランザクション バリア関数を使用して、複数回の再試行後に 1 回のみの成功した送信が行われるようにします。

処理機能を次のように調整します。

func sagaBarrierAdjustBalance(sdb *sql.Tx, uid int, amount int) (interface{}, error) {
    _, err := dtmcli.StxExec(sdb, "dtm_busi.user_account を更新し、balance を balance + ? に設定し、user_id を ? に設定、amount、uid)
    dtmcli.ResultSuccess、err を返します

}

func sagaBarrierTransIn(c *gin.Context) (インターフェース{}, エラー) {
    dtmcli.ThroughBarrierCall(sdbGet(), MustGetTrans(c), func(sdb *sql.Tx) (interface{}, error) を返します {
        sagaBarrierAdjustBalance(sdb, 1, reqFrom(c).Amount) を返します。
    })
}

func sagaBarrierTransInCompensate(c *gin.Context) (インターフェース{}, エラー) {
    dtmcli.ThroughBarrierCall(sdbGet(), MustGetTrans(c), func(sdb *sql.Tx) (interface{}, error) を返します {
        sagaBarrierAdjustBalance(sdb, 1, -reqFrom(c).Amount) を返します。
    })
}

ここでのdtmcli.TroughBarrierCall呼び出しは、サブトランザクション バリア テクノロジを使用して、3 番目のパラメータのコールバック関数が 1 回だけ処理されるようにします。

この TransIn サービスを複数回呼び出すと、残高は 1 回だけ調整されます。次のコマンドを実行すると、新しいプロセスを実行できます。

go run app/main.go saga_barrier

4.3 ロールバックの処理

銀行がユーザー2に金額を振り込む準備をしているときに、ユーザー2の口座に異常を発見し、失敗を返した場合はどうなりますか?転送操作が失敗を返すように処理機能を調整します

func sagaBarrierTransIn(c *gin.Context) (インターフェース{}, エラー) {
    dtmcli.ResultFailure、nil を返す
}

トランザクション失敗の相互作用のタイミング図を示します。

ここで一つ問題があります。TransIn の順方向操作は何もせず失敗を返しました。このとき、 TransInの補正操作を呼び出すとTransIn逆方向調整がうまくいかなくなるのでしょうか?

心配しないでください。以前のサブトランザクション バリア テクノロジにより、送信前にTransInエラーが発生した場合、補正は何も行われないことが保証されます。送信後にTransInエラーが発生した場合、補正操作によってデータが 1 回送信されます。TransIn TransInまだ進行中の場合、補正操作は、補正/空のロールバックを送信する前に、TransIn の最終的な送信/ロールバックを待機します。

エラーを返す TransIn を次のように変更できます。

func sagaBarrierTransIn(c *gin.Context) (インターフェース{}, エラー) {
    dtmcli.ThroughBarrierCall(sdbGet(), MustGetTrans(c), func(sdb *sql.Tx) (インターフェース{}, エラー) {
        sagaBarrierAdjustBalance(sdb, 1, 30) を返します
    })
    dtmcli.ResultFailure、nil を返す
}

最終的な結果は、バランスはまだ良好であるということです

5. まとめ

この記事では、分散トランザクションの基本的な理論をいくつか紹介し、よく使用される分散トランザクション ソリューションについて説明します。記事の後半では、トランザクション例外の原因、分類、および優れたソリューションについても説明します。最後に、実行可能な分散トランザクションの例を使用して、短いプログラムで以前に紹介した内容を説明します。

これで、MySQL と Golan の分散トランザクションに関する 7 つの古典的なソリューションに関するこの記事は終了です。分散トランザクションに関する 7 つの古典的なソリューションの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL XA で分散トランザクションを実装する方法
  • MySQLクエリトランザクション処理へのノード接続の実装
  • MySQL データベース トランザクション例のチュートリアル
  • MySQLトランザクションが効率に与える影響の分析と概要
  • MySQL トランザクション分離レベルの詳細
  • MySQLデータベースのトランザクションとインデックスの詳細な説明
  • MySQL トランザクション分析

<<:  <td></td> タグの境界線スタイルがブラウザに表示されない問題の解決方法

>>:  データ URI スキームを使用して Web ページに画像を埋め込む方法の紹介

推薦する

星のフラッシュ効果を実現するjs

この記事の例では、スターフラッシュ効果を実現するためのjsの具体的なコードを参考までに共有しています...

MySQL関連のツールをいくつかお勧めします

序文:インターネット技術の継続的な発展に伴い、MySQL 関連のエコシステムはますます充実し、ますま...

Vueはドラッグ可能なツリー構造図を実装します

目次Vue 再帰コンポーネントドラッグイベント最近、Vue を使用して、ドラッグ可能なツリー構造図と...

ウェブサイトメンテナンスページのリスト構築のヒント

また、多くの場合、メンテナンスのために Web サイトを少なくとも数分間オフラインにする必要がありま...

MySQL のデッドロック チェックとデッドロック除去の例の詳細な説明

1. クエリプロセスプロセスリストを表示2. 対応するプロセスを照会し、IDを強制終了します。検証(...

JavaScriptアップロードファイル制限パラメータケースの詳細な説明

プロジェクトシナリオ: 1. アップロードファイルの制限関数: 1. フロントエンド操作による異常な...

JavaScriptはXiaomi Mall公式サイトの完全なページ実装プロセスを模倣します

目次1. ホームページ制作1. ダウンロードアプリの制作2. ナビゲーションバーの制作3. カルーセ...

Nginx ベースのアクセス制御と接続制限の実装

序文Nginxの組み込みモジュールは、同時リクエスト数の制限とリクエストのソースの制限をサポートして...

HTML ウェブページでのアンカー(名前付きアンカー)の使用の概要

以下の情報はインターネットから収集したものです1. アンカーは、Web ページ作成におけるハイパーリ...

MySQL ユーザー変数と set ステートメントの例の詳細な説明

目次1 ユーザー変数の概要2 ユーザー変数の定義3 ユーザー変数の使用3.1 セットを通した例3.2...

CentOS に Nginx をインストールする方法

公式ドキュメント: https://nginx.org/en/linux_packages.html...

Alibaba Cloud MySQL スペースをクリーンアップする方法

今日、Alibaba Cloudからディスク警告通知を受け取りました。確認したところ、100Gのスペ...

MySQL トリガーの紹介、トリガーの作成、使用制限の分析

この記事では、例を使用して、MySQL トリガーの概要、トリガーの作成方法、およびトリガーの使用上の...

MySQLデータ損失の原因と解決策

目次序文問題の説明原因分析拡大する総括する序文最近、データの欠落やデータの損失に関するフィードバック...

Linux でファイルを削除するさまざまな方法の効率の比較

Linux で大量のファイルを削除する効率をテストします。まず500,000個のファイルを作成する$...