マイクロサービスアーキテクチャのコンテキストでの分散トランザクションの問題

こんにちは。すでに9月に、OTUSはコース「HighloadArchitect」の新しいグループのセットをオープンします。この点に関して、私はこのコースのために特別に書かれた一連の出版物を継続します。また、OTUSのコースプログラムとトレーニング形式について詳しく説明する無料のウェビナーに招待します。こちらからウェビナーにサインアップできます








前書き



ご存知のように、モノリスからマイクロサービスアーキテクチャへの移行は、プロジェクトの技術的な部分と人的要因の両方に関連する多くの問題を引き起こします。最も難しい技術的課題の1つは、分散システムの一貫性確保することです。



一貫性



かなり微妙な点は、分散システムのコンテキストでの一貫性は、データベースのコンテキストでの一貫性とは異なるということです。さらに、一貫性とは、正確に最初のことを意味します。不完全な(誤った)操作は効果をもたらさず、データを変更しません。データへの同時アクセスでは、データに複数のコピーがある場合、すべての操作はアトミックと見なされます(操作の中間結果は表示されません)(複製)の場合、すべてのコピーに操作を適用する順序は同じです。つまり、実際には、ACIDトランザクションを受信したいのですが、分散トランザクションのみを受信したいと考えています。



問題の原因



マイクロサービスアーキテクチャで一貫性を維持することが難しいのはなぜですか?実際のところ、このアーキテクチャスタイルでは、サービスパターンごとにデータベースを使用することがよくあります。このパターンは、各マイクロサービスが独自の独立したベースを持っているという事実にあることを思い出してください(たとえば、プライマリデータソースに加えて、キャッシュを使用できるため、ベース)。このアプローチでは、一方ではマイクロサービス間に暗黙のデータ形式リンクを追加せず(マイクロサービスはAPIを介してのみ明示的に相互作用します)、他方ではテクノロジーに依存しないなどのマイクロサービスアーキテクチャの利点を最大限に活用できます(マイクロサービスの特定の負荷に適したデータストレージテクノロジーを選択できます) )。しかし、これらすべてにより、データの一貫性の保証が失われました。自分で判断するモノリスは、ACIDトランザクションを提供する機能を提供する1つの大きなデータベースと通信しました。現在、多くのデータベースがあり、1つの大きなACID(トランザクション)の代わりに、多くの小さなACID(トランザクション)があります。私たちの仕事は、これらすべてのトランザクションを1つにまとめることです。分散



楽観的な一貫性



最初に頭に浮かぶのは、楽観的な一貫性の概念です。必要な数のストレージエンジンに対して、必要な数のトランザクションをコミットします。同時に、私たちはすべてがうまくいくことを期待し、すべてが悪い場合、私たちは最終的にすべてがうまくいくと言います。最終的にすべてが悪い場合は、「はい、これは起こりますが、確率は非常に低いです」と言います。



冗談はさておき、ビジネス上重要ではないときに一貫性を無視することは、特にそれを維持するためにどれだけの労力がかかるかを考えると、良い考えです(これについては後で説明します)。



一貫性オプション



一貫性がビジネスにとって重要である場合、それを達成しようとするいくつかの方法があります。データが1つのサービスによって更新される状況(たとえば、データベースレプリケーションがある)について話している場合は、PaxosやRaftなどの標準の整合性アルゴリズムを適用できます。このようなトランザクションは同種と呼ばれます。データが複数のサービスによって更新された場合(つまり、異種トランザクションが発生した場合)、上記で説明した複雑さはどのように始まりますか。



一方では、サービスベースのアーキテクチャを追求することで、分散トランザクションを提供する必要性を回避できます(トランザクションが均一になるようにサービスを組み合わせます)。このようなソリューションは、マイクロサービスアーキテクチャの原則の観点からはあまり標準的ではありませんが、技術的にははるかに単純であるため、実際によく使用されます。一方、正規のマイクロサービスを離れることはできますが、同時に、分散トランザクションを保証するためのメカニズムの1つである2フェーズコミットまたはサガを適用します。この記事では、最初のオプションについて説明し、次回は2番目のオプションについて説明します。



2フェーズコミット



メカニズムは非常に単純です。実際にトランザクションを調整するトランザクションマネージャーがいくつかあります。最初の段階(準備)で、トランザクションマネージャーはリソースマネージャーに適切なコマンドを発行します。これに従って、コミットされるログにデータを書き込みます。すべてのリソースマネージャーから第1ステージが正常に完了したことの確認受け取った後、トランザクションマネージャーは第2ステージを開始し、次のコマンド(commit)を発行します。これに従って、リソースマネージャーは以前に受け入れた変更を適用します。



その明らかな単純さにもかかわらず、このアプローチには多くの欠点があります。まず、第2フェーズで少なくとも1つのリソースマネージャーに障害が発生した場合、トランザクション全体をロールバックする必要があります。したがって、マイクロサービスアーキテクチャの原則の1つであるフォールトトレランスに違反しています(分散システムに到達したとき、その障害は標準であり、例外的な状況ではないとすぐに想定しました)。さらに、失敗が多い場合(そして失敗が多い場合)、トランザクションをキャンセルするプロセスを自動化する必要があります(トランザクションをロールバックするトランザクションの書き込みを含む)。次に、トランザクションマネージャ自体が単一の障害ポイントです。彼はトランザクションにid-shnikをトランザクションで発行できるはずです。第三に、特別なコマンドがリポジトリに与えられるので、リポジトリがこれを実行できるはずであると想定するのは論理的です。つまり、XA標準に準拠しており、すべての最新テクノロジーがXA標準に準拠しているわけではありません(Kafka、RabbitMQなどのブローカーおよびMongoDBやCassandraなどのNoSQLソリューションは2フェーズコミットをサポートしていません)。



これらすべての要因からそれ自体を示唆する結論は、クリス・リチャードソンによって美しく明確に表現されました:「2PCはオプションではありません」(2フェーズコミットはオプションではありません)。



出力



分散トランザクションがマイクロサービスアーキテクチャの主な技術的問題である理由を理解し、この問題を解決するためのさまざまなオプションについて説明し、2フェーズのコミットメカニズムについて詳しく説明しました。






私は誰を招待コースについての私のセミナーにサインアップするために、私はトレーニング形式について詳細にあなたを伝えるとトレーニングプログラムに皆を紹介しますします、。






続きを読む:






All Articles