web-dev-qa-db-ja.com

マイクロサービスでは、サービスごとに単一のデータベースまたは単一のデータベースインスタンスですか?

マイクロサービスアーキテクチャの各サービスには独自のデータベースが必要であることを理解しています。ただし、独自のデータベースを使用するということは、実際には、同じデータベースインスタンス内に別のデータベースが存在する、または文字通り別のデータベースインスタンスが存在するということですか?

これによって、私はデータベースの共有を意味するのではなく、それはノー・ノーですが、むしろデータベース・インスタンスです。

たとえば、AWSを使用していて3つのサービスがある場合、単一のRDSインスタンスでサービスごとに3つのデータベースを作成しますか、それとも3つのサービスのそれぞれで独立して使用されるデータベースをそれぞれ含む3つのRDSインスタンスを作成しますか?

単一のRDSインスタンスで複数のデータベースを使用する方がよい場合、次の理由により、独立したサービスを提供する目的に反することになります。

  1. RDSインスタンスのリソースはサービス間で共有されます。特定の時間にデータベースを頻繁に使用する可能性のあるサービスAは、異なるデータベースを使用するが同じRDSインスタンス上にあるサービスBに影響を与えますか?

  2. すべてのサービスは、そのRDSインスタンスのデータベースバージョンに依存します。

53
xenon

それは実際には、スケーラビリティの要件と、マイクロサービスインスタンスが単一の結果を提供するためにどのように/連携する必要があるかによって異なります。それはトレードオフが何であるかを知るのに役立ちます:

すべてを1つのデータベースに保存する

  • より簡単な設定
  • サービスの他のインスタンスとの調整や通信は必要ありません
  • 完全なデータセットを見つけやすくなります
  • データベースのパフォーマンスによって制限されるシステムパフォーマンス

データベースを分離しておく

  • リクエストの完全な回答がマイクロサービスインスタンス全体に分散している可能性があります
  • その場合、リクエストを解決するためにコミュニケーションと交渉を増やしました
  • そのマイクロサービスノードを失うときのデータの処理(データベースがまだ稼働している場合でも、適切な構成の新しいノードが立ち上がるまで、データを取得できません)
  • 構成の複雑さの増大

あなたが解決している問題は何ですか?

場合によっては、一時的なデータのみが心配になります。データベースがダウンしても、大きな問題ではありません。そのような場合、最初からデータベースは必要ないかもしれません。すべてをメモリに保持し、物事を驚くほど高速にしてください。これが最も扱いやすいソリューションです。

他の場合では、データの整合性が必要ですが、データベースは、ノードの数に基づいて容量を拡張できます。この場合、おそらく単一のデータベースで十分であり、応答性を個別に管理することが正しい答えです。

その間にはいくつかのケースがあります。たとえば、地域固有のデータベースがあり、サービスのインスタンスごとに異なる地域にある別のデータベースがあるとします。通常、シャーディングデータベースはリージョン間でうまく機能しないため、これはデータを少しローカライズし、調整を自分で制御する方法です。

教義と現実

私は、マイクロサービスとそれらがどのようにモジュール化されるべきかについて、多くの記事を読みました。推奨事項は、フロントエンド、マイクロサービス、データ層を1つの単位として保持することから、すべてのインスタンスのデータベースやフロントエンドコードを共有することまで、多岐にわたります。通常、より多くの分離が最大のスケーラビリティを提供しますが、複雑さが増すという犠牲を伴います。

マイクロサービスの計算が重い場合は、必要に応じてそれらのマイクロサービスの数をスケールできるようにすることは理にかなっています。データベースやフロントエンドコードを共有しても、このアプローチは妨げられません。

実際のところ、プロジェクトの特定のニーズには、作業をタイムリーに実行し、測定しているシステム負荷を処理するために、さまざまな妥協が必要です(さらにもう少し)。完全に分離されたフロントエンド、マイクロサービス、およびデータ層のトリオを高尚な目標と考えてください。システムに対する需要が高まるほど、その目標に近づく必要があります。私たちはすべてではありません[insert name of highly successful web entity here]、そして彼らは彼らが今いるところから始めませんでした。場合によっては、完全ではない状況から始めて、それで満足する必要があります。

22
Berin Loritsch

同じ種類のDBシステムとバージョンを使用できるいくつかのサービスがあると仮定すると、異なるデータベースまたはdbインスタンスを使用する場合は、設計時に行う必要がない決定です。代わりに、展開時に決定できるようにする必要があります。これは、簡単に構成できます。他のサービスのデータベースがホストされている場所にとらわれないようにサービスを設計します。

運用中は、1つのインスタンスから開始できます。システムが正常に動作する場合は、そのままにしておきます。ただし、1つのインスタンス上の異なるデータベースが共有するリソースが多すぎるため、これがシステムに適切に拡張されないことに気付いた場合、それが役立つ場合は、常に異なるインスタンスを使用するオプションがあります。

したがって、サービスの2つにリソースの共有を許可したからといって、サービスはマイクロサービスアーキテクチャに違反しません。リソースの共有が必須になったときに違反します。

72
Doc Brown

それは問題ではありません。

理論的に問題になる可能性がある唯一のシナリオは、1つのサービスがデータベースの異なるバージョンに移行する必要がある場合です。しかし、それでも、最初から個別のインスタンスを作成することと、その1つのサービスを共有インスタンスから個別のサービスに移行することには、実際の違いはありません。実際には、このシナリオのためだけに個別のインスタンスを持つことは、YAGNIの例だと思います。

13

RDSインスタンスは単一のボックスです。 1つのインスタンスに複数のデータベースがある場合、それらはCPU /メモリなどを共有します。

マイクロサービスのパフォーマンスがデータベースのパフォーマンスによって制限されている場合:マイクロサービスの複数のコピーをデプロイします。それぞれ異なるデータベースを使用しますが、各データベースは同じRDSインスタンス上にあります。意味がない*(フェイルオーバーを除く)。マイクロサービスクラスターは、単一のマイクロサービスと同じ速度で実行されます

ただし、データベースのパフォーマンスに制約されるマイクロサービスは珍しいと言えます。

通常、マイクロサービスはデータベースからデータを取得し、ロジックを実行して、データベースに情報を書き込みます。パフォーマンスのボトルネックはlogicであり、選択や挿入ではありません。

この場合、すべてのマイクロサービスインスタンス間で同じデータベースを単に共有できます

3
Ewan

データベースをサービスに対してプライベートに保つ目的は、カプセル化です。マイクロサービスは、システム内の他のサービスがパブリックインターフェイスを介して使用するブラックボックスです。

このカプセル化が機能するプレーンは2つあります。

  • 1つ目は、アプリケーションレベルでの論理です。サービスはシステム内のいくつかのビジネスオブジェクトを所有しており、これらのオブジェクトに関する状態を永続化する必要があります。一部の特定のデータベースがこれらのビジネスオブジェクトをサポートしているのは、実装の詳細にすぎません。別のデータベースを保持することにより、他のサービスが実装にバックドアアクセスできないようにして、代わりにパブリックインターフェイスを使用するように強制します。ここでの目標は、クリーンなアーキテクチャーと規律あるプログラミングです。サービスがデータベースを見つけることができるように接続の詳細が適切である限り、データベースが正確に存在する場所はこのレベルには関係ありません。

  • 2番目のレベルは操作可能です。ご指摘のとおり、設計が完全なブラックボックスであっても、1台のマシンに配置されたさまざまな作業がリソースを奪い合う可能性があります。これは、個別の論理データベースを個別のマシンに配置するのに十分な理由です。他の回答が指摘しているように、ニーズがそれほど厳しくなく、予算が厳しい場合、これは単一のマシンでのコロケーションの実用的な議論です。ただし、いつものように、トレードオフ:この設定では、システムの成長に応じて、より多くのベビーシッターが必要になる場合があります。予算が許せば、私はほとんどの場合、2つのタスクを実行するのに2つの別々の小さなマシンを使用するよりも、1つの大きなマシンを共有することを好みます。

1
ben author

ここでもう少し理論的になると役立つと思います。マイクロサービスの背後にある動機付けのアイデアの1つは、何も共有しないメッセージパッシングプロセスです。マイクロサービスは、アクターモデルのアクターのようなものです。つまり、各プロセスは独自のローカル状態を維持し、1つのプロセスが別のプロセスの状態にアクセスする唯一の方法は、メッセージを送信することです(さらに、他のプロセスはメッセージに好きな方法で応答できます)。 「すべてのマイクロサービスが独自のデータベースを持っている」とは、プロセスの状態(つまり、マイクロサービス)がlocalおよびprivateであることを意味します。これは、「データベース」がマイクロサービスとともにcollocatedであること、つまり、「データベース」がマイクロサービスと同じ論理ノードに格納され、実行されることを意味します。マイクロサービスの異なる「インスタンス」は個別のプロセスであるため、それぞれに独自の「データベース」が必要です。

グローバルデータベースまたはマイクロサービス間で共有されるデータベース、またはマイクロサービスのインスタンスでさえ、この観点からは共有状態を構成します。マイクロサービスの観点からこれを処理する「適切な」方法は、「データベース」マイクロサービスが仲介する共有データベースを用意することです。データベースの内容について知りたい他のマイクロサービスは、その「データベースマイクロサービス」にメッセージを送信します。これは通常、元のマイクロサービスのローカル状態(つまり、マイクロサービスインスタンス「データベース」ごと)の必要性を排除しません!変化するのは、そのローカルな状態が表すものです。 「User Sally is a admin」ではなく、「データベースマイクロサービスが5分前に「User Sallyは管理者である」と言った」と保存します。つまり、完全に制御する状態を超えて、他のマイクロサービスの状態に関するbeliefsを格納します。

これの利点は、各マイクロサービスが自己完結型であることです。これにより、マイクロサービスが障害の最小単位になります。 (ほとんど)部分的に機能している状態のマイクロサービスについて心配する必要はありません。もちろん、問題はマイクロサービスのネットワークに移されています。マイクロサービスは、他のマイクロサービスに接続できないため、目的の機能を実行できない場合があります。ただし、メリットは、マイクロサービスが明確な状態になり、低下したサービスや限定されたサービスを提供できる可能性があることです。時代遅れの信念を取り除くことによって。欠点は、システム全体の一貫したスナップショットを取得するのが非常に難しく、かなりの(望ましくない)冗長性と重複が存在する可能性があることです。

もちろん、提案はすべてのDockerコンテナーにOracleのインスタンスを貼り付けることではありません。まず、すべてのマイクロサービスに「データベース」が必要なわけではありません。一部のプロセスは、正常に動作するために永続的な状態を必要としません。たとえば、2つのプロトコル間を変換するマイクロサービスは、必ずしも永続的な状態を必要としません。永続的な状態が必要な場合、「データベース」という単語は「永続的な状態」の単なる単語です。必要に応じて、JSONが含まれているファイル、Sqliteデータベース、ローカルで実行されているOracleのコピー、またはデータを永続的に保存するlocallyの他の方法を使用できます。 「データベース」がローカルでない場合、純粋なマイクロサービスの観点からは、別の(マイクロ)サービスのように扱う必要があります。このため、RDSインスタンスをマイクロサービスの「データベース」にすることは意味がありません。繰り返しになりますが、視点は「独自のRDSデータベースを備えた一連のマイクロサービス」ではなく、「と通信する RDSデータベースを備えた一連のマイクロサービス」です。この時点では、データが同じデータベースインスタンスに格納されているかどうかに関係なく、違いはありません。

実用的には、マイクロサービスアーキテクチャはhugeの複雑さを追加します。この複雑さは、部分的な障害に真剣に対処する代償です。多くの場合、メリットに値しない可能性が高いのはやり過ぎです。最も有益と思われる方法でシステムを自由に設計できます。シンプルさと効率に関する懸念が、純粋なマイクロサービスアーキテクチャからの逸脱につながる可能性は十分にあります。コストは追加のカップリングになり、サービス間の目に見えない相互作用や、自由に展開して拡張する自由に対する制限など、独自の複雑さをもたらします。