データベース |分散トランザクションの実装原理の詳細な説明

データベース |分散トランザクションの実装原理の詳細な説明

トランザクションは、データベース システムにおいて非常に興味深く重要な概念です。これは、データベース管理システムの実行プロセスにおける論理単位です。トランザクション内のすべての操作が実行されるか、実行されないかを確認できます。今日の SOA およびマイクロサービス アーキテクチャでは、複数の分散サービスにおけるビジネスの一貫性を確保するには、分散トランザクションを実装する必要があります。

[[274102]]

この記事では、トランザクションの実装原則、分散トランザクションの理論的根拠、実装原則について紹介します。

取引

この記事の冒頭で、トランザクションはデータベース管理システムの実行プロセスにおける論理単位であると述べました。一連のデータベース操作が完全に実行されるか、まったく実行されないかのいずれかを保証できます。トランザクションを通じてデータベースをある状態から別の状態に移行できます。それぞれの状態において、データベース内のデータは一貫性を保ちます。

データベースとトランザクション

データベース トランザクションには、原子性、一貫性、独立性、永続性の 4 つの特性があります。


トランザクションの基本

上記の 4 つの特性は ACID と略されることが多く、データベース トランザクションの実装原則は、実際にはこの 4 つの特性を実装する原則です。

実施原則

MySQL でのトランザクションの実装に関する前回の記事「概要と説明」では、ACID トランザクションの基本的なプロパティを実装する方法について、比較的詳細な概要と分析を示しました。ここでは、さらにいくつかの重要な実装の詳細を簡単に紹介します。詳細については、上記の記事をお読みください。

トランザクションログ

トランザクションが実行中にいつでもロールバックできること (アトミック性) と、コミットされたトランザクションがデータベースに永続的に保存されることを保証するために、トランザクション ログを使用してトランザクション実行中のデータベースの変更を保存します。各トランザクション ログには、トランザクション ID、現在変更されている要素、変更前後の値が含まれます。

トランザクションログ

上記のトランザクション ログを取得したら、必要になったときにトランザクションをロールバックするのは非常に簡単です。データベースは上記のログに基づいて逆の操作を生成し、トランザクションが発生する前の状態を復元します。トランザクションをロールバックしてアトミック性を確保できるだけでなく、トランザクション ログは永続性も実現できます。トランザクションがデータベースを変更すると、実際にはログが生成され、ディスクに更新されます。ログの書き込み操作は追加操作なので非常に高速です。その後、対応するレコードがデータベースに書き込まれるか、更新されます。

MySQL の最も一般的なストレージ エンジン InnoDB には、実際には 2 種類のトランザクション ログがあります。1 つはロールバック ログ (undo ログ) で、もう 1 つは redo ログ (redo ログ) です。前者はトランザクションのアトミック性を保証し、後者はトランザクションの永続性を保証します。これら 2 つは総称してトランザクション ログと呼ばれます。

同時実行制御

最も重要なバックエンド サービスであるため、各データベース操作をシリアルでのみ実行した場合のパフォーマンスへの影響を想像するのは困難です。ただし、同時 SQL 実行のプロセスでは、データベースの分離要件が保証されない可能性があります。結局のところ、これは一貫性、分離性、パフォーマンスの間のトレードオフです。


トレードオフと並行性

同時実行によって生じる一貫性の問題を回避し、データベースの分離要件を満たすために、データベース システムでは、マシンの効率を最大限に利用するための同時実行制御メカニズムがよく使用されます。一般的な同時実行制御メカニズムは、ロック、タイムスタンプ、および MVCC です。


同時実行制御

悲観的同時実行制御メカニズムとして、ロックはリソースを更新する前にロックするために使用されます。これにより、複数のデータベース セッションが同時にレコードの行を変更した場合に予期しない動作が発生しないことが保証されます。タイムスタンプは、各送信時にリソースが変更されたかどうかを確認するために使用されます。

分散トランザクション

広い意味では、分散トランザクションは実際にはトランザクションです。ただし、ビジネス定義やマイクロサービス アーキテクチャ設計の問題により、複数のサービス間でのビジネスのトランザクション性、つまり 4 つの ACID 特性を確保する必要があります。単一マシンのデータベース トランザクションが分散トランザクションになると、元の単一マシンで比較的信頼性があったメソッド呼び出しやプロセス間通信方式は使用できなくなります。同時に、ネットワーク通信が不安定になることが多いため、サービス間の情報伝達に支障が生じます。


tx および分散 tx

モジュール (またはサービス) 間の通信方法の変更が、分散トランザクションの複雑さの主な原因です。同じトランザクションで複数のコードを実行すると、ネットワークの不安定性によりさまざまな奇妙な問題が発生します。ネットワーク経由で他のサービスのインターフェースを要求すると、多くの場合、正解、失敗、タイムアウトの 3 つの結果が返されます。成功しても失敗しても、ユニークで明確な結果を得ることができます。タイムアウトは、リクエストの発信者が受信者がリクエストを正常に処理したかどうかを確認できないことを意味し、これも多くの問題の原因となります。


通信の信頼性とトランザクション

システム間の通信の信頼性は、単一システム内では信頼できるものから、マイクロサービス アーキテクチャ間では信頼できないものへと変化しました。分散トランザクションは、実際には、信頼性の低い通信の下で実装されるトランザクションの特性です。トランザクションであっても分散トランザクションであっても、アトミック性は永続ストレージへの依存を避けることはできません。トランザクションはディスク上のログを使用して実行プロセスとコンテキストを記録するため、ロールバックまたは補正が必要かどうかをログを通じて追跡できます。分散トランザクションは、トランザクションの実行プロセスを追跡するために、データベース、Zookeeper、ETCD などのサービスにも依存します。つまり、さまざまな形式のログは、トランザクションのいくつかの主要な特性を確保するための重要な手段です。

2PCと3PC

2 フェーズ コミットは、トランザクションをコミットするときに分散システム内のすべてのノード間の一貫性を確保するために設計されたプロトコルです。分散システムでは、すべてのノードは操作を実行した後、自身のステータスを認識しますが、他のノードのステータスを認識することはできません。トランザクションが複数のシステムにまたがる場合、すべてのノードの制御を統一し、操作の結果を実際にコミットするかどうかを指示するコーディネーターとしてコンポーネントを導入する必要があります。分散システムで一貫性を実現しようとする他のプロトコルは、2 フェーズ コミットに基づく改善です。


2フェーズコミット

2 フェーズ コミットの実行プロセスは、その名前が示すように、投票フェーズとコミット フェーズの 2 つのフェーズに分かれています。投票フェーズでは、コーディネーターはトランザクション参加者 (コホート) に操作要求を実行できるかどうかを尋ね、他の参加者の応答を待ちます。参加者は対応するトランザクション操作を実行し、REDO ログとロールバック ログを記録します。正常に実行されたすべての参加者は、実行操作の結果を示すために、AGREEMENT または ABORT をコーディネータに送信します。


2 段階コミット投票フェーズ

すべての参加者が明確な結果(合意または終了)を返すと、2 フェーズ コミットはコミット フェーズに入り、コーディネータは投票フェーズの返された結果に基づいてすべての参加者にコミットまたはロールバックの指示を送信します。


2 フェーズ コミット コミット フェーズ

トランザクションのすべての参加者がトランザクションをコミットすることを決定すると、コーディネーターは参加者に COMMIT 要求を送信します。操作を完了してリソースを解放すると、参加者はコーディネータに完了メッセージを返します。コーディネータがすべての参加者から完了メッセージを受信すると、トランザクション全体が終了します。逆に、参加者が現在のトランザクションを中止することを決定した場合、コーディネーターはトランザクションの参加者にロールバック要求を送信します。参加者は、前回の操作のロールバック ログに従って操作をロールバックし、完了メッセージをコーディネータに送信します。コミット フェーズでは、現在のトランザクションがコミットされるかロールバックされるかに関係なく、すべてのリソースが解放され、トランザクションは確実に終了します。

2 フェーズ コミット プロトコルはブロッキング プロトコルです。つまり、2 フェーズ コミットの実行中に、トランザクションの実行中にコーディネータが永久にクラッシュすると、トランザクションの一部の参加者はトランザクションを完了できなくなります。コーディネータが COMMIT または ROLLBACK メッセージを送信するのを待機することになり、複数の参加者の状態に一貫性がないという問題が発生する可能性もあります。


2 フェーズコミットの問題

3PC

2 フェーズ コミット プロトコルのいくつかの問題を解決するために、3 フェーズ コミットではタイムアウト メカニズムと準備フェーズが導入されています。コーディネーターまたは参加者が指定された時間内に他のノードから応答を受信しない場合、現在のステータスに基づいてトランザクション全体をコミットするか終了するかを選択します。準備フェーズの導入により、トランザクション参加者にはロールバック以外のオプションが実際に提供されます。


3 フェーズコミット図

参加者がコーディネータに ACK を送信した後、コーディネータから長時間応答がない場合、デフォルトでは、参加者はタイムアウトしたトランザクションを自動的にコミットし、2 フェーズ コミットのようにブロックされません。上の図は、さまざまな段階でコーディネータまたは参加者のタイムアウトによってどのような動作が発生するかを明確に示しています。

XA トランザクション

MySQL の InnoDB エンジンは、実際には分散トランザクション (XA トランザクションと呼ばれることが多い) をサポートできます。 XA トランザクションは、前のセクションで説明した 2 フェーズ コミット プロトコルを使用して分散トランザクションを実装します。この分散トランザクションでは、トランザクション マネージャーがコーディネーターとなり、リソース マネージャーが分散トランザクションの参加者となります。


2 フェーズ コミットと XA トランザクション

この時点で、MySQL で XA トランザクションがどのように実装されているかについては、すでに明確な考えがあります。

  • リソース マネージャーは、トランザクション リソースにアクセスする機能を提供します。データベースは、管理するトランザクションをコミットまたはロールバックできる共通のリソース マネージャーです。
  • トランザクション マネージャーは、分散トランザクション全体のさまざまな部分を調整します。複数のリソース マネージャーと通信して、それらが管理するトランザクション (トランザクション全体から分岐するすべてのもの) を処理します。

分散トランザクションとトランザクション

2 フェーズ コミット プロトコルで定義されているように、MySQL が提供する XA インターフェイスは、プロトコルの投票フェーズとコミット フェーズを簡単に実装できます。次のフローチャートを使用すると、MySQL XA インターフェースがどのように使用されるかを簡単に理解できます。


mysql-xa-トランザクション状態

XA は確かに強力な一貫性を保証できますが、MySQL XA の実行中は、対応するリソースがロックされ、他のトランザクションがリソースにアクセスできなくなります。トランザクションに長時間 COMMIT または ROLLBACK がない場合、実際にはデータベースに重大な影響を及ぼします。

佐賀

2 フェーズ コミットは実際にはトランザクションの強力な一貫性を保証できますが、多くのビジネス シナリオでは、ビジネスの最終的な一貫性のみを保証する必要があります。一定の時間枠内では、複数のシステムにおけるデータの不整合は許容されます。時間枠が過ぎると、すべてのシステムから一貫した結果が返されます。

Saga は、実際には簡略化された分散トランザクション ソリューションです。一連の分散操作を一連のローカル トランザクションに変換します。各ローカル トランザクションでは、データベースを更新し、クラスター内の他のサービスに新しいメッセージを送信して、次のローカル トランザクションをトリガーします。ビジネス ロジックの違反によりローカル トランザクションが失敗すると、一連のロールバック操作が直ちにトリガーされ、以前のローカル トランザクションによって発生した副作用が元に戻されます。

LLT

ローカル データベース トランザクションと比較すると、長いトランザクションは一部のデータベース リソースを比較的長い期間保持するため、他の通常のデータベース トランザクションの実行に重大な影響を及ぼします。この問題を解決するために、ヘクター・ガルシア・モリーナとケネス・セーラムは 1987 年に論文「Sagas」を発表しました。

LLT を一連の絡み合った重複するデータベース トランザクションに書き換えることができる場合、この LLT は Saga です。データベース システムは、Saga 内の一連のトランザクションがすべて正常に実行されるか、またはその補正トランザクションがすべての副作用をロールバックできることを保証し、分散トランザクション全体の最終的な一貫性を確保します。 Saga のコンセプトとその実装は非常にシンプルですが、システム全体の処理能力を向上させる大きな可能性を秘めています。


長期トランザクションとトランザクション

トランザクションが長く複雑になるほど、例外によってロールバックされたりデッドロックされたりする可能性が高くなります。 Saga は LLT を複数の短いトランザクションに分解し、トランザクションがロールバックされるリスクを大幅に軽減できます。

コラボレーションとオーケストレーション

Saga モードを使用して分散トランザクションを開発する場合、さまざまなサービスを調整する方法は 2 つあります。1 つは振り付け、もう 1 つはオーケストレーションです。


サガパターン

分散トランザクションを共同で開発する場合、各ローカル トランザクションは他のサービスでのローカル トランザクションの実行をトリガーします。つまり、トランザクション実行プロセスはストリーム形式で実行されます。


サガパターン振り付け

トランザクションを処理するために協調的なアプローチを使用することを選択した場合、サービス間の通信は実際にはイベントを通じて実行されます。各ローカル トランザクションは最終的に、メッセージ キュー内のメッセージまたは RPC 要求などの新しいイベントをダウンストリーム サービスに送信します。ダウンストリームによって提供されるインターフェースは、べき等性と再入可能性を保証する必要があります。

さらに、共同で作成された分散トランザクションには、実際には明らかな集中型ノードは存在しません。複数のサービス参加者間の相互作用プロトコルはグローバルに定義する必要があります。各サービスが処理および送信できるイベントとインターフェースは、より厳密に設計する必要があり、可能な限り抽象度の高いイベントまたはインターフェースを提供する必要があります。この方法でのみ、各サービスは自律性を実現し、既存のコードとロジックを再利用できます。

分散トランザクションを処理するために協調的なアプローチを使用しない場合は、オーケストレーション方式で分散トランザクションを実装することもできます。オーケストレーション アプローチでは、集中型コーディネーター ノードが導入されます。 Saga オブジェクトを使用して、すべてのサブタスクの呼び出しステータスを追跡し、タスクの呼び出しステータスに基づいて対応する補正プランを呼び出すかどうかを決定し、ネットワーク要求がタイムアウトしたときに再試行します。


サガパターンオーケストレーション

ここでは、現在の分散トランザクションのステータスを保存し、状況に応じてトランザクションをロールバックまたはコミットする集中型の「コーディネーター」を紹介します。サービス オーケストレーションのプロセスでは、コーディネーター自体からトランザクション全体の実行プロセスを考慮します。共同作業方式と比較すると、オーケストレーションの実装プロセスは比較的簡単です。

コラボレーションとオーケストレーションは、実際には完全に反対の 2 つのモデルです。前者は各サービスの自律性と分散性を重視しますが、後者はトランザクション実行プロセスを統一的に管理するために集中型コンポーネントを必要とします。両者の長所と短所は、実は集中化と分散化の長所と短所です。集中型ソリューションでは、多くの場合「ゴッドサービス」が作成されますが、これには他のノードを整理して統合するための多くの作業が含まれ、単一点障害の問題も発生します。分散型ソリューションは、管理とデバッグに不便をもたらします。業務の実行プロセスを追跡する必要がある場合、複数のサービスにまたがる必要があり、メンテナンスのコストが増加します。

下流の制約

分散トランザクションの開発に Saga を使用することを選択した場合、分散トランザクションの参加者には一定の制約が課せられます。取引の各参加者は、次の点を確認する必要があります。

インターフェースと副作用を補うインターフェースを提供します。

インターフェースは再入可能性をサポートし、グローバルに一意の ID を通じて冪等性を保証します。

この方法により、ネットワーク通信のタイムアウトが発生したときに長いトランザクションを再試行できることを保証できると同時に、トランザクションをロールバックする必要があるときにロールバック インターフェイスを呼び出して目的を達成できます。

まとめ

実際、Saga モデルは、トランザクションの 4 つの基本的な ACID プロパティを同時に満たすという考えを完全に放棄しています。代わりに、分散トランザクションの実装の難しさを軽減し、リソースの同期とロックによって発生する問題を軽減することを選択します。基本的なビジネス可用性と最終的な一貫性を実現するために、BASE (基本的な可用性、ソフト、最終的な一貫性) トランザクションを実装することを選択します。ほとんどのビジネス シナリオでは、最終的な一貫性を実現することで、基本的にすべてのビジネス ニーズを満たすことができます。極端なシナリオでは、2 フェーズ コミットを選択するか、エラーが発生しやすい分散トランザクションの実装を放棄し、単一のマシンでデータベース トランザクションを使用して問題を解決する必要があります。

メッセージサービス

分散トランザクションが複雑さをもたらす理由は、実際にはモジュール間の通信が不安定なためです。ネットワーク リクエストを行うと、返される結果は成功、失敗、またはタイムアウトになります。


ネットワーク通信

ネットワークが成功を返すか失敗を返すかは、実際には確実な結果です。ネットワーク要求がタイムアウトすると、実際には処理が非常に困難になります。この時点では、発信者は要求が配信されたかどうか確信が持てず、要求の結果もわかりませんが、メッセージ サービスは特定のメッセージが発信者に配信されることを保証できます。ほとんどのメッセージ サービスは、2 つの異なる QoS、つまりサービス レベルを提供します。


メッセージ配信 QoS

最も一般的な 2 つのサービス レベルは、At-Most-Once と At-Least-Once です。前者は、送信者が受信者がメッセージを受信できるかどうかを保証しないことを保証します。メッセージは一度配信されるか、配信されないかのどちらかであり、これは実際には通常のネットワーク要求とあまり変わりません。 At-Least-Once は、メッセージ配信の失敗の問題を解決できます。送信者は配信結果を確認し、失敗またはタイムアウトの場合はメッセージを再配信する必要があります。送信者は、受信者がメッセージを受信したことを確認するまで、メッセージをプッシュし続けます。 At-Most-Once と比較すると、At-Least-Once はメッセージの配信を保証できるため、より多くの人が使用します。

これら 2 つの一般的なサービス レベルに加えて、Exactly-Once という別のサービス レベルがあります。このサービス レベルは、送信者だけでなく消費者にも要件を課します。受信側は受信したすべてのメッセージを重複排除する必要があります。送信者と受信者はメッセージを再試行し、相手側はメッセージを重複排除します。これら 2 つはそれぞれ異なるノードにデプロイされます。このように、各ノード上のサービスについては、それらの間の通信は Exactly-Once になります。ただし、Exactly-Once では受信者の参加が必要であることに注意してください。

AMQP プロトコルのメッセージ キューを実装することで、分散トランザクションを実装できます。プロトコル標準では、tx_select、tx_commit、および tx_rollback という 3 つのトランザクション関連インターフェイスが定義されています。このうち、tx_select はトランザクションを開始でき、tx_commit と tx_rollback はそれぞれトランザクションをコミットまたはロールバックできます。

メッセージ サービスを使用して分散トランザクションを実装する基本原理は、他の方法とそれほど変わりません。唯一の違いは、メッセージ サービスを使用すると、メッセージの永続性と再試行機能を実装でき、開発者が使用するためのより合理的な API インターフェイスを提供できることです。

要約する

分散トランザクションの実装は、分散システムにおいて非常に重要な問題です。マイクロサービス アーキテクチャと SOA の普及により、分散トランザクションの原則と使用方法を習得することは、バックエンド開発者が習得すべきスキルになりました。 ACID トランザクション用の 2PC および 3PC の実装から、BASE 補償トランザクション用の Saga の実装、そして最終的にはトランザクション メッセージを通じてメッセージが正常に消費されることを非同期的に保証することまで、システムのスループットと可用性を向上させるために、システムの一貫性要件を徐々に削減してきました。

ビジネスで一貫性がそれほど強く求められていない場合、著者は通常、Saga プロトコルを使用して分散トランザクションを設計および開発します。実際の業務では、強力な一貫性のあるトランザクションを必要とするビジネス シナリオはほとんどありません。最終的な一貫性を実現し、脳の分裂や矛盾が発生したときに補償することで問題を解決できるため、ほとんどすべての問題を解決できます。

参照

データベーストランザクション · Wikipedia

MySQL でのトランザクションの実装

MySQL · 機能分析 · MySQL 5.7 における XA トランザクションの改善に関する簡単な説明

XA トランザクション

2相コミットプロトコル

パターン: サガ

サガ

RocketMQ 4.3が正式にリリースされ、分散トランザクションをサポート

Akka メッセージ配信 - 最大 1 回、最小 1 回、正確に 1 回

パート 1 最大 1 回

パート2 少なくとも1回

パート3 正確に1回

メッセージ配信の信頼性

<<:  戦略計画に影響を与えるマルチクラウド ストレージの 6 つの課題

>>:  サーバーレスが IT 環境に与える影響

推薦する

適切なクラウド サービス プロバイダーを選択するにはどうすればよいでしょうか? IDCの見解を見る

コロナ後のクラウドの成長とクラウドサービス市場の変化を評価するIDCレポート2件「IDC Marke...

ユニリーバの大規模クラウド移行の経験と教訓

世界的な消費財大手ユニリーバは最近、400 を超える家庭用ブランドすべてを Microsoft の ...

産業用 IoT PaaS プラットフォームの防御、破壊、分離

序文: 「寿宝礼」は日本の剣道の学習法から始まり、後に他の武術や産業に発展しました。 「修」とは、最...

クラウド コンピューティングによる混乱を経験している 3 つのホットな市場はどれですか?

クラウド ネイティブ コンピューティングは現在、業界最大かつ最も影響力のあるクラウド コンピューティ...

分散MemCacheの詳細な解釈

MemCacheとはMemCache は、動的な Web アプリケーションがデータベースの負荷を軽減...

Xiongzhanghaoのアカウントインデックスを迅速に改善するにはどうすればよいですか?ガイドを添付します!

月給5,000~50,000のこれらのプロジェクトはあなたの将来ですXiong Zhang アカウン...

Amazon Web Services と F1® がパートナーシップを深め、イノベーションを推進

2022年11月10日、フォーミュラ・ワン・ワールドチャンピオンシップ®(以下、F1®)は、アマゾン...

事業運営は「赤字」状態から脱却する

電子商取引の成長に伴い、伝統的な中小企業の教育業界は徐々に電子商取引にまで拡大し、多数の中小企業がこ...

アリババクラウドとHuyaが共同でライブストリーミング業界向けのエッジノードとクラウドエンタープライズネットワークサービスを初めて開始

2018年11月22日、アリババグループが主催する広東ビッグデータ開発者会議と2018年広東雲奇会議...

テンセントカンファレンスアプリマーケットが正式に開始、第一弾には20以上のアプリが登場

6月30日、テンセント会議アプリマーケットが正式に開始され、企業や開発者に数億のトラフィックの入り口...

ユーザーの立場に立ってウェブサイトのユーザーエクスペリエンスを向上させる

検索エンジンは、ウェブサイトのユーザー エクスペリエンスにますます注目しています。結局のところ、検索...

無料でSEOを学ぶ方法を探している初心者

私のオンライン名は Dream です。コンピューターを使い始めて 3 か月ですが、インターネットはま...

SEOとネットワークマーケティングの関係についての簡単な説明

現在、国内の状況はトレンドに追随しています。最近、SEOの台頭により、多くのSEOトレーニング機関が...

知虎陣地戦

「疑問があれば、答えはある。」これは質疑応答コミュニティ「知乎」の新しいスローガンで、公開前の昨年の...