「分散トランザクション」、今回は完全に理解できました!

「分散トランザクション」、今回は完全に理解できました!

分散サービスやマイクロサービスが普及している今日では、誰もがこれらの用語に精通していると思います。分散型または分割型のマイクロサービスを使用する利点については、確かに多くのことが考えられます。

[[269005]]

画像はBaotu.comより

たとえば、各自が個別のサービスだけを保守すればよく、以前のようなコードの競合は発生しなくなります。テスト、リリース、またはアップグレードを行う場合は、記述したコードのみに注意を払う必要があります。とても便利で親切です!

しかし、物事には二面性があり、問題も生じます。今日の記事では、分散システム アーキテクチャによってもたらされる厄介な問題の 1 つである分散トランザクションについて説明します。

トランザクションとは何ですか?

まず、質問しましょう。トランザクションとは何でしょうか?トランザクションとは、同時に成功するか失敗するかの一連の操作であると考える人もいます。次に、トランザクションの ACID 特性 (原子性、一貫性、独立性、および耐久性) から始めます。

実際、トランザクションは一連の操作が正常に実行できることを保証するものであり、ACID 特性も満たす必要があります。

しかし、今日は別の視点から考えてみましょう。私たちは、何(たとえば、トランザクションとは何か)だけでなく、なぜ(たとえば、なぜトランザクションという概念があるのか​​、トランザクションはどのような問題を解決しようとしているのか)も知っておく必要があります。

場合によっては、視点を変えることで異なる結果が得られることがあります。

物事を別の視点から見る

古典文学作品が人生から生まれながらも人生よりも高尚であるように、情事の概念も人生から生まれます。 「情事」の導入は、何らかの問題を解決するためであるに違いない。そうでなければ、誰がそんな退屈なことをするでしょうか?

最も単純で典型的な例: 銀行振込で、口座 A から口座 B に 1,000 元を送金したいとします。

通常、口座Aから口座Bに1000を送金すると、口座Aの残高は1000減少し(この操作はAction1で表されます)、口座Bの残高は1000増加します(この操作はAction2で表されます)。

まず、Action1 と Action2 は 2 つの操作であることを明確にする必要があります。操作が 2 つあるため、実行順序が必要です。

その後、Action1 が実行され、Action2 を実行しようとしているときに問題が発生する可能性があります (たとえば、データベースが過負荷になり、一時的にアクセスが拒否されるなど)。

日常生活に例えると、私が友人に1,000元を送金したところ、私のカードの残高が1,000元減ったのに、友人はお金を受け取っていないということになります。

「お金はどこへ行ったのか」という問題を解決するために、「取引」という概念が導入されました。つまり、たとえば送金時に 100% の成功を保証することはできないため、銀行システムは 99.99% の高可用性しか保証できないため、その 0.01% の時間に上記の問題が発生した場合、銀行システムは直接アクション 1 をロールバックします (つまり、残高に 1,000 元を戻します)。

銀行システムの場合、Action1 と Action2 が 0.01% の確率で同時に成功することを保証できない可能性があります。すると、問題が発生すると、両方が同時に故障することが保証されます。 (トランザクションの原子性)

この例を通じて、冒頭で提起した 2 つの質問 (なぜトランザクションが存在するのか? トランザクションはどのような問題を解決するのか?) に対する答えが得られました。

要約すると、トランザクションは ACID プロパティを使用して、どのような状況でも一連の操作が安全かつ正確に実行されることを保証します。

Java でのトランザクション

トランザクションについて理解できたので、次は身近なものを見てみましょう。 Java ではトランザクションはどのように機能しますか?

Java で最もよく使用されるのは、サービス レイヤーの追加、削除、変更メソッドに @Transactional アノテーションを追加して、Spring がトランザクションの管理を支援できるようにすることです。

最下層では、サービス コンポーネントに対応する Proxy 動的プロキシが生成され、サービス コンポーネントのすべてのメソッドが対応する Proxy によって引き継がれるようになります。

Proxy が add() などの対応するビジネス メソッドを呼び出すと、Proxy は AOP の考え方に基づいて、実際のビジネス メソッドを呼び出す前に setAutoCommit(false) を実行してトランザクションを開きます。

次に、ビジネス メソッドが実行された後に Commit を実行してトランザクションをコミットします。ビジネス メソッドの実行中に例外が発生した場合は、Rollback を実行してトランザクションをロールバックします。

もちろん、@Transactional アノテーションの具体的な実装の詳細については、この記事の焦点では​​ないため、ここでは詳しく説明しません。この記事のトピックは「分散トランザクション」です。 @Transactional アノテーションに興味がある場合は、デバッグ ソース コードを自分で分解して調べることができます。ソースコードを見れば真実が分かります。

分散トランザクションとは何ですか?

長い準備期間を経て、ようやくこの記事の最初のポイントにたどり着きました。まず、トランザクションがあり、Spring の @Transactional アノテーションを使用してトランザクションを制御するのは非常に便利なのに、なぜ分散トランザクションの概念を考案する必要があるのか​​、考えたことがありますか。

さらに、分散トランザクションと通常のトランザクションの関係は何ですか?違いは何ですか?分散トランザクションはどのような問題を解決しますか?

さまざまな疑問が次々と湧いてきます。心配しないで。これらの考えを念頭に置いて、分散トランザクションについて詳しく説明しましょう。

分散トランザクションというくらいですから、分散に関係があるんでしょうね!簡単に言えば、分散トランザクションとは、分散システム内のトランザクションを指します。

では、続けましょう。まず、次の図を見てください。

上の図に示すように、モノリシック システムには、従業員モジュール、財務モジュール、休暇モジュールの 3 つのモジュールがあります。これで、これら 3 つのモジュール内のインターフェースを順番に呼び出す必要がある操作ができました。

この操作はトランザクションに含まれた全体であり、同時に成功するか、または失敗して同時にロールバックされます。成功しなければ、死んでしまうでしょう。それは何も悪いことではありません。

しかし、モノリシック システムを分散システムまたはマイクロサービス アーキテクチャに分割すると、トランザクションは上記のように簡単ではなくなります。

まず、以下に示すように、分散システムに分割した後のアーキテクチャ図を見てみましょう。

上の図は、分散システムで同じ操作を実行する様子を示しています。従業員モジュール、財務モジュール、休暇モジュールは、それぞれ従業員システム、財務システム、休暇システムに分割されます。

たとえば、ユーザーが操作を実行する場合、この操作では、まず予備処理のために従業員システムを呼び出し、次に HTTP または RPC を介して財務システムと休暇システムのインターフェースをそれぞれ呼び出して、さらに処理する必要があります。それらの操作はデータベースに個別に実装する必要があります。

これら 3 つのシステムの一連の操作は、実際には同じ分散トランザクションにラップされる必要があります。このとき、これら 3 つのシステムの操作は同時に成功するか、失敗するかのいずれかになります。

分散システムで操作を完了するには、通常、上記の例のように、複数のシステム間で調整された呼び出しと通信が必要です。

従業員システム、財務システム、休暇システムの 3 つのサブシステムは、単一システム内の異なるモジュール間の呼び出しではなく、HTTP または RPC を介して通信します。これが分散システムと単一システムの最大の違いです。

普段は分散アーキテクチャにあまり注意を払わない学生の中には、これを読んだ後に「Spring の @Transactional アノテーションを使えばいいのに、なぜそんなに気にする必要があるんだ」と言う人もいるかもしれません。

しかし、ここで非常に重要な点があります。モノリシック システムは同じ JVM プロセスで実行されますが、分散システム内の各システムは独自の JVM プロセスで実行されます。

したがって、@Transactional アノテーションを直接追加することはできません。これは、同じ JVM プロセス内のトランザクションのみを制御でき、複数の JVM プロセスにまたがるトランザクションに対しては無力だからです。

分散トランザクションの実装アイデア

分散トランザクションとは何かがわかったところで、分散トランザクションはどのように機能するのでしょうか?ここでは、分散トランザクションの実装ソリューションをいくつか紹介します。

信頼性の高いメッセージ最終一貫性ソリューション

全体のフローチャートは以下のとおりです。

このプログラムの一般的なプロセスを説明しましょう。

  • システム A はまず、MQ に Prepared メッセージを送信します。 Prepared メッセージの送信に失敗した場合、操作はキャンセルされ、後続の操作は実行されません。
  • メッセージが正常に送信されると、システム A のローカル トランザクションが実行されます。実行が失敗した場合、MQ はメッセージをロールバックするように指示され、後続の操作は実行されません。
  • システム A のローカル トランザクションが正常に実行された場合、MQ に確認メッセージを送信するように指示します。
  • システム A が確認メッセージの送信に失敗した場合はどうなりますか?このとき、MQ はすべての Prepared メッセージを定期的に自動的にポーリングし、システム A によって事前に提供されたインターフェースを呼び出して、システム A の最後のローカル トランザクションが正常に実行されたかどうかを確認します。
  • 成功した場合、確認メッセージが MQ に送信されます。失敗した場合、MQ はメッセージをロールバックするように指示されます。 (以降の操作は実行されなくなります)
  • このとき、システム B は確認メッセージを受信し、ローカル トランザクションを実行します。ローカル トランザクションが正常に実行された場合、トランザクションは正常に完了します。
  • システム B のローカルトランザクションが失敗した場合はどうなりますか? MQ の再試行に基づいて、MQ は成功するまで自動的に再試行します。本当に失敗した場合は、アラームを送信して手動でロールバックして補正することができます。

このソリューションの重要な点は、MQ に基づいて継続的に再試行でき、最終的には成功するということです。

実行が失敗する一般的な理由は、ネットワークのジッターやデータベースの負荷が高すぎることなど、一時的な問題です。

このソリューションにより、データの最終的な一貫性が 99.9% のケースで保証されます。残りの0.1%に問題がある場合は、手動でデータを修復することができます。

適用可能なシナリオ: このソリューションは広く使用されています。現在、国内のインターネット企業のほとんどはこの考え方に基づいています。

*** プログラムの周知活動

全体のフローチャートは以下のとおりです。

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

  • システム A のローカル トランザクションが実行された後、メッセージが MQ に送信されます。
  • MQ を消費する専用の *** 努力通知サービスが存在します。このサービスは MQ を消費し、それを記録のためにデータベースに書き込むか、メモリ キューに格納します。次に、システム B のインターフェースを呼び出します。
  • システム B が正常に実行された場合、すべて問題ありませんが、システム B に障害が発生した場合はどうなるでしょうか?
  • そして、この時点で、*** はサービスに通知して、システム B を定期的に再度呼び出すことを N 回繰り返します。 *** がまだ失敗した場合は、諦めます。

このソリューションと上記の信頼性の高いメッセージの結果的一貫性ソリューションの違いは、信頼性の高いメッセージの結果的一貫性ソリューションでは、システム A のトランザクションが完了している限り、システム B のトランザクションは継続的に再試行 (*** 回) することで常に完了することを保証できることです。

ただし、ベストエフォート方式は異なります。システム B のローカル トランザクションの実行に失敗した場合、N 回再試行してから再試行を停止します。システム B のローカルトランザクションが完了しない可能性があります。どの程度「厳しく」制御するかについては、独自のビジネスに基づいて設定する必要があります。

たとえば、電子商取引システムでは、注文後に注文が成功したことをユーザーに通知するテキスト メッセージが送信されるビジネス シナリオでは、注文は正常に完了します。ただし、テキスト メッセージの送信に関しては、テキスト メッセージ サービスに一時的な問題が発生し、3 回の再試行後に失敗します。

このシナリオでは 3 回が最善の努力であると考えられるため、SMS メッセージの送信はこれ以上試行しません。

要約すると、指定された再試行回数内で実行が成功すれば、誰もが満足します。再試行回数が***を超える場合は諦めて再試行しないでください。

適用可能なシナリオ: 一般的に、重要度の低い業務オペレーションで使用されます。つまり、完了すれば満足できるが、失敗しても悪い影響はないようなシナリオです。

たとえば、前述の電子商取引の一部の通知テキスト メッセージは、分散トランザクションを確実にするために、このベスト エフォート通知ソリューションを使用する方が適しています。

TCC 強力な一貫性ソリューション

TCC の正式名称は次のとおりです。

  • 試す
  • 確認する
  • キャンセル

これは実際には補償の概念を使用しており、次の 3 つの段階に分かれています。

  • 試行フェーズ: このフェーズでは、各サービスのリソースをテストし、リソースをロックまたは予約します。
  • 確認フェーズ: このフェーズでは、各サービスで実際の操作を実行します。
  • キャンセル フェーズ: サービスのビジネス メソッドの実行に失敗した場合は、正常に実行されたビジネス ロジックをロールバックする補正が必要になります。

例を挙げてみましょう:

たとえば、銀行間で送金する場合、2 つの銀行間の分散取引が行われます。 TCC ソリューションを使用して実装する場合、考え方は次のようになります。

  • 試行段階: まず 2 つの銀行口座の資金を凍結し、あらゆる操作を防止します。
  • 確認段階: 実際の振込操作を実行し、銀行口座 A の資金が減額され、銀行口座 B の資金が増加します。
  • キャンセル段階: いずれかのバンクの操作が失敗した場合、補償のためにロールバックする必要があります。たとえば、銀行 A の口座の資金が引き落とされたが、銀行 B の口座の資金が増加しなかった場合、銀行 A の口座の資金を再び追加する必要があります。

適用可能なシナリオ: 正直なところ、このソリューションが使用されることはほとんどなく、私たちも比較的まれにしか使用していませんが、使用できるシナリオはあります。

なぜなら、このトランザクションのロールバックは、実際にはロールバックして補正するための独自のコードを記述することに大きく依存しており、補正コードは膨大で非常に面倒なものになるからです。

たとえば、一般的に、お金、お金の取り扱い、支払い、取引に関連するシナリオでは、TCC を使用して、分散トランザクションがすべて成功するか、すべて自動的にロールバックされることを厳密に保証し、資金の正確性を厳密に保証し、資金に関する問題が発生しないようにします。

適切なシナリオ: 非常に高い一貫性要件があり、それが共通資金調達シナリオなどのシステムの中核シナリオでない限り、TCC ソリューションを使用できます。

多くのビジネス ロジックを自分で記述し、トランザクション内の各リンクが正常かどうかを判断する必要があります。そうでない場合は、補正/ロールバック コードを実行します。

そして最も良い点は、各事業の実行時間が比較的短いことです。しかし、正直に言うと、一般的にはこれを行わないようにしてください。ロールバックロジックや補償ロジックを自分で書くのは本当に面倒ですし、ビジネスコードの保守も困難です。

要約する

この記事では、分散トランザクションとは何かを紹介し、最も一般的に使用される 3 つの分散トランザクション ソリューションを紹介します。

しかし、上記のソリューションに加えて、実際には 2 フェーズ コミット ソリューション (XA ソリューション) とローカル メッセージ テーブル ソリューションが存在します。

しかし、正直に言うと、これらのソリューションを使用している企業はごくわずかです。スペースの都合上、紹介は省略させていただきます。後で別の記事を書く機会があれば、これら 2 つのソリューションのアイデアについて詳しく説明します。

Chinese Huperzine: 10 年以上の BAT アーキテクチャ経験、一流インターネット企業のテクニカル ディレクター。数百人のチームを率いて、数億のトラフィックを処理する複数の高同時実行システムを開発しました。長年の研究で蓄積してきた研究論文や経験の要約を文書にまとめましたので、皆様にご紹介したいと思います。 WeChat 公開アカウント: Shishan’s Architecture Notes (ID: shishan100)。

<<:  Docker コンテナをバックグラウンドで実行する方法 (デタッチ モード)

>>:  データベース開発のギャップを越え、分散データベース技術の動向について議論する

推薦する

装飾会社のウェブサイト最適化の簡単な分析

国慶節のゴールデンウィークが近づいています。この一週間の休日を待つのは特に辛いですか? SEO 最適...

spinserver: 開始まで 15 分/米国の超ハイエンド サーバー、月額 89 ドルから、10G 帯域幅、40 コア/80 スレッド/768G メモリ/8T SSD

spinserver は、米国西海岸のサンノゼと中央データセンターであるダラスで独立サーバー事業に注...

説明: 内部ページの関連性と品質を最適化する方法は、掲載の前提条件です。

多くのウェブサイトのホームページが Baidu に含まれているのに、ウェブサイトの内部ページがまだ含...

百度改革の憶測:もはや簡単には手配できない

百度の激動の時期を経て、百度がランキング戦略を調整していることは誰もが知っているはずです。しかし、百...

TragicServers - 年間 21 ドル / メモリ 1g / スワップ 512 / コア 4 個 / ハードディスク 65g / トラフィック 2T

悲劇的なサーバー、ははは、このTragicServersを「言葉にできない」と翻訳するたびに、イライ...

DockerのエントリポイントとCMDの違い

Docker の Entrypoint と Cmd はどちらも、コンテナの起動時に実行されるコマンド...

Microsoft Ignite China の詳細な読み物 |クラウド上の6つのデータ機能の長所と短所

過去 2 年間で、デジタル変革は劇的に加速しました。そして、この変革プロセスにおいてはクラウド戦略が...

検索エンジンがSEOに与える影響

中国インターネットネットワークインフォメーションセンター(CNNIC)による2008年中国検索エンジ...

アマゾン ウェブ サービス、「地域に根ざしたグローバルな優位性」を掲げる中国戦略を開始

アマゾンウェブサービスは7月21日、上海で開催された「2021アマゾンウェブサービス中国サミット」で...

サイト運営経験: 訪問者を維持することは、ウェブサイトの将来性を意味します

今では、大規模なウェブサイトから小規模なセルフメディアプラットフォームまで、誰もが訪問者を維持する方...

分散コンピューティングにおけるデータ品質に関する講演

[[442615]] 1. 概要1. データ品質の問題はどこにでもある基本的に、データを利用するすべ...

年初マーケティング:ブランドが3.8国際女性デーをどう活用できるか

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービステキスト | 脳を燃やす...

インターネットプロモーションはインターネットだけに頼ることはできません。オンラインとオフラインを組み合わせてみてはいかがでしょうか。

SEO 担当者として、このタイトルを見て、ナンセンスだと思いますか? ネットワーク プロモーションは...

床塗料のキーワードランキングを向上させる6つの戦略

現在でも、バックリンクは、Baidu や Google などの検索エンジンがウェブサイトの人気度を測...

百度、今日頭条、広東通など5大チャンネルの詳しい説明

チャネルに精通しているということは、宣伝する製品に適したチャネルを選択できるかどうかを意味します。ま...