私が慣れている以上に妥協する多くのソリューションがあります。確かに、異なる銀行間でお金を移動するなど、ユースケースが複雑な場合、より快適な代替手段は不可能かもしれません。しかし、マイクロサービスの使用がデータベーストランザクションと干渉する一般的なシナリオでできることを見てみましょう。
オプション1:可能な限りトランザクションの必要性を回避する
明白で前に言及しましたが、管理できれば理想的です。コンポーネントは実際に同じマイクロサービスに属していましたか?または、トランザクションが不要になるようにシステムを再設計できますか?おそらく、非トランザクション性を受け入れることが最も手頃な犠牲です。
オプション2:キューを使用する
他のサービスが私たちがやりたいことに成功するのに十分な確実性がある場合、何らかの形式のキューを介してそれを呼び出すことができます。キューに入れられたアイテムは後までピックアップされませんが、アイテムがキューに入れられていることを確認できます。
たとえば、単一のトランザクションとしてエンティティを挿入し、電子メールを送信するとします。メールサーバーを呼び出す代わりに、テーブル内の電子メールをキューに入れます。
Begin transaction
Insert entity
Insert e-mail
Commit transaction
明らかな欠点は、複数のマイクロサービスが同じテーブルにアクセスする必要があることです。
オプション3:トランザクションを完了する直前に、外部作業を最後に行う
このアプローチは、トランザクションのコミットが失敗する可能性が非常に低いという前提に基づいています。
Begin transaction
Insert entity
Insert another entity
Make external call
Commit transaction
クエリが失敗した場合、外部呼び出しはまだ行われていません。外部呼び出しが失敗した場合、トランザクションはコミットされません。
このアプローチには、1つの外部呼び出ししか作成できないという制限があり、最後に実行する必要があります(つまり、クエリでその結果を使用することはできません)。
オプション4:保留状態の物を作成する
ここに投稿されているように、複数のマイクロサービスに異なるコンポーネントを作成させ、それぞれを非トランザクションで保留状態にすることができます。
検証は実行されますが、最終的な状態では何も作成されません。すべてが正常に作成されると、各コンポーネントがアクティブになります。通常、この操作は非常に単純で、何か問題が発生する確率は非常に小さいため、非トランザクションでアクティベーションを行うことを好む場合もあります。
最大の欠点は、おそらく保留中のアイテムの存在を考慮する必要があることです。選択クエリでは、保留中のデータを含めるかどうかを考慮する必要があります。ほとんどは無視する必要があります。そして、更新はまったく別の話です。
オプション5:マイクロサービスにクエリを共有させる
他のオプションはありませんか?次に、非正統派を取得しましょう。
会社によっては、これは受け入れられない場合があります。私は知っています。これは非正統的です。受け入れられない場合は、別のルートに進みます。しかし、これがあなたの状況に合っていれば、問題を簡単かつ強力に解決します。それは、最も受け入れられる妥協案にすぎないかもしれません。
複数のマイクロサービスからのクエリを単純な単一のデータベーストランザクションに変換する方法があります。
クエリを実行するのではなく、返します。
Begin transaction
Execute our own query
Make external call, receiving a query
Execute received query
Commit transaction
ネットワークに関しては、各マイクロサービスが各データベースにアクセスできる必要があります。将来のスケーリングに関しても、このことに留意してください。
トランザクションに関係するデータベースが同じサーバー上にある場合、これは通常のトランザクションになります。それらが異なるサーバー上にある場合、それは分散トランザクションになります。コードは関係なく同じです。
接続タイプ、パラメータ、接続文字列を含むクエリを受け取ります。フローを読みやすい状態に保ちながら、きちんとした実行可能なCommandクラスにまとめることができます。マイクロサービス呼び出しは、トランザクションの一部として実行するCommandになります。
接続文字列は、発信元のマイクロサービスが提供するものであるため、すべての意図および目的に対して、クエリは依然としてそのマイクロサービスによって実行されていると見なされます。クライアントマイクロサービスを介して物理的にルーティングするだけです。それは違いがありますか?それで、別のクエリと同じトランザクションに入れることができます。
妥協が容認できる場合、このアプローチにより、マイクロサービスアーキテクチャでのモノリスアプリケーションの単純なトランザクション性が得られます。