web-dev-qa-db-ja.com

別のマイクロサービスが「所有」しているデータベースからデータを読み取るのがなぜ悪いのか

私は最近、マイクロサービスアーキテクチャに関するこの優れた記事を読みました: http://www.infoq.com/articles/microservices-intro

Amazonにウェブページをロードすると、100以上のマイクロサービスが連携してそのページを提供すると述べています。

その記事では、マイクロサービス間のすべての通信はAPIを介してのみ行うことができると説明しています。私の質問は、すべてのデータベースの書き込みはAPIを介してのみ行うことができると言うのがとても悪いのですが、さまざまなマイクロサービスのデータベースから直接自由に読み取ることができる理由です。たとえば、マイクロサービスの外部からアクセスできるデータベースビューはごくわずかであるため、マイクロサービスを維持しているチームは、これらのビューに変更を加えない限り、マイクロサービスのデータベース構造を変更できることを認識できます。欲しいです。

ここで何か不足していますか? API経由でのみデータを読み取る必要がある他の理由はありますか?

言うまでもなく、私の会社はアマゾンよりもかなり小さく(そして常にそうなるでしょう)、私たちが持つことができるユーザーの最大数は約500万人です。

67
David

データベースは、情報の隠蔽があまり得意ではありません。これは、実際に情報を公開することを目的としているため、かなりありそうです。しかし、カプセル化に関しては、これはそれらを粗末なツールにします。なぜカプセル化が必要なのですか?

シナリオ:いくつかのコンポーネントをRDBMSに直接結び付け、1つの特定のコンポーネントがデータベースの非正規化が必要なパフォーマンスのボトルネックになることを確認しましたが、他のすべてのコンポーネントが影響を受けるため、そうすることができません。 RDBMSよりも、ドキュメントストアやグラフデータベースのほうがよいことに気づくかもしれません。データが小さなAPIによってカプセル化されている場合、必要な方法でAPIを再実装する現実的な機会があります。キャッシュレイヤーを透過的に挿入できます。

アプリケーション層から直接ストレージ層をいじくり回すことは、 依存関係の逆転の原理 が提案することの正反対です。

73
back2dos

マイクロサービスのより重要で重要なものは何ですか?そのAPIまたはそのデータベーススキーマ?それは他の世界との契約だからです。データベーススキーマは、サービスによって管理されるデータを格納するための便利な方法であり、マイクロサービスのパフォーマンスを最適化する方法で整理されることを願っています。開発チームはいつでもそのスキーマを自由に再編成でき、またはまったく異なるデータストアソリューションに切り替えられるはずです。その他の国は気にしないでください。 APIはコントラクトであるため、APIがいつ変更されるかは、世界の他の国々が気にします。

今、あなたが彼らのデータベースを覗きに行くなら

  • スキーマに不要な依存関係を追加します。彼らはあなたのサービスに影響を与えずにそれを変更することはできません。
  • あなたは彼らの内部に不要で予測できない負荷を加えます。
  • 独自のサービスのパフォーマンスは、データベースのパフォーマンスの影響を受けます(クライアントのパフォーマンスを最適化するためにserviceを最適化し、サービスのパフォーマンスのみをデータベースが最適化しようとします)。
  • データストア内のリソースを正確かつ明確に表すことができないスキーマに実装を関連付けています。これには、内部状態を追跡したり、特定の実装を満たすためにのみ必要な追加の詳細が含まれている可能性があります(気にする必要はありません)。
  • あなたは彼らのサービスの状態を無意識に破壊または破壊するかもしれません(そして彼らはあなたがこれをしていることを知らないでしょう)
  • リソースが更新されたことを知らなくても、リソースをデータベースから更新、削除、削除できます。

読み取りアクセスのみが許可されている場合、最後の2つのポイントは発生しない可能性がありますが、他のポイントは十分な理由以上のものです。共有データベースは悪いことです。

経験の浅い開発者(または学んでいない開発者)は、データベースをサービスよりも重要であると見なし、データベースをrealのことであると見なし、サービスは、サービスを取得するための単なる方法です。それ。それは間違った方法です。

57
itsbruce

マイクロサービスアーキテクチャの説明は難しいですが、それを考える最良の方法は、コンポーネント指向アーキテクチャとサービス指向アーキテクチャの融合です。スイートとしてのソフトウェアは、非常に具体的なビジネスドメインの責任を持つ多くのスモールビジネスコンポーネントで構成されています。提供されるサービスまたは必要なサービスのいずれかでの外部世界へのインターフェースは、明確に定義されたサービスのAPIを介して行われます。

コンポーネントのビジネスドメインの外部にあるデータベースへの書き込み、およびデータベースからの読み取りは、このスタイルのアーキテクチャに反します。

これの主な理由は、別のソフトウェアコンポーネントによってサービスを通じて提供されるAPIは、サービス提供コンポーネントの新しいリリースが利用可能になると、APIが後方互換性を持つ可能性が最も高いと合理的に予想されるためです。私が「提供」コンポーネントの開発者である場合は、APIへの下位互換性についてのみ心配する必要があります。私のデータベースに対して直接カスタムクエリを作成した他の3つの開発チームがあることを知っている場合、私の仕事ははるかに複雑になります。

さらに悪いことに、これらを書いた他のチームが重要なプロジェクトのスプリントの途中であり、コンポーネントからこの変更を受け入れることができない可能性があります。現在、所有しているビジネスドメインでのコンポーネントのソフトウェア開発は、別のビジネスドメインでの開発によって推進されています。

サービスを介した完全な相互作用により、さまざまなソフトウェアコンポーネント間の結合が減少するため、このような状況はそれほど頻繁に発生しません。データベースのビューを使用する他のコンポーネントに関しては、他の誰かがそれに対してクエリを作成した場合、ビューに下位互換性を持たせることができます。ただし、これは例外的なケースであり、アプリケーションが膨大な量のデータを読み取る必要がある場合は、おそらくレポートまたはバッチ処理に対してのみ行う必要があると私はまだ感じています。

明らかに、これは、開発チームがAmazonのようなビジネスドメインによって分離されている大規模な分散チームでうまく機能します。小規模な開発ショップである場合でも、特に大きなプロジェクトに迅速に立ち向かう必要がある場合や、ベンダーソフトウェアに対処する必要がある場合は、このモデルを利用できます。

16
maple_shaft

過去20年間に、いくつかの大規模なモジュラーデータベース設計を見てきました。Davidが提案するシナリオで、アプリケーションが独自のスキーマ/テーブルセットへの書き込みアクセスと別のスキーマ/読み取りアクセスへのアクセスを持っている状況を何度か見ました。テーブルのセット。ほとんどの場合、アプリケーション/モジュールが読み取り専用アクセス権を取得するこのデータは、 "マスターデータ"として記述できます。

その当時は、以前の回答が示唆していたはずの問題は見たことがなかったので、以前の回答で指摘されたポイントを詳しく見てみる価値があると思います。

シナリオ:いくつかのコンポーネントをRDBMSに直接結び付け、1つの特定のコンポーネントがパフォーマンスのボトルネックになるのを確認します

このコメントにも同意しますが、これは、マイクロサービスがローカルでデータのコピーを読み取れるようにするための引数でもあります。つまり、最も成熟したデータベースはレプリケーションをサポートしているため、開発者が何もしなくても、「マスターデータ」をマイクロサービスデータベースに物理的に複製できます。必要。

これを古い形で「エンタープライズデータベース」として認識し、コアテーブルを「部門別データベース」に複製する人もいます。ここでのポイントは、変更されたデータ(差分のみ、バイナリ形式で、ソースデータベースへの最小限のコストで)の組み込みレプリケーションでデータベースがこれを実行するのが一般的に良いことです。

逆に、データベースの選択でこれが「既製」のレプリケーションサポートで許可されていない場合、「マスターデータ」をマイクロサービスデータベースにプッシュしたいという状況に陥る可能性があり、これにより開発者の多大な労力とまた、実質的に効率の悪いメカニズムでもあります。

データベースを非正規化したいかもしれませんが、他のすべてのコンポーネントが影響を受けるため、それはできません

私にとって、この発言は正しくありません。非正規化は「付加的な」変更であり、「重大な変更」ではなく、非正規化が原因でアプリケーションが破損することはありません。

これがアプリケーションを壊す唯一の方法は、アプリケーションコードが「select * ...」のようなものを使用し、余分な列を処理しない場合です。私にとってそれはアプリケーションのバグでしょうか?

非正規化はどのようにしてアプリケーションを壊しますか?私にはFUDのように聞こえます。

スキーマの依存関係:

はい、アプリケーションはデータベーススキーマに依存するようになりました。これは、これが大きな問題になるはずであることを意味しています。余分な依存関係を追加することは明らかに理想的ではありませんが、私の経験では、データベーススキーマへの依存関係は問題ではなかったので、なぜそうなのでしょうか。運が良かった?

マスターデータ

通常、マイクロサービスに読み取り専用アクセスを許可する可能性があるスキーマは、最も一般的には、エンタープライズの「マスターデータ」と説明するものです。企業に不可欠なコアデータがあります。

歴史的にこれは、依存関係を追加するスキーマが成熟していて安定していることを意味します(企業にとってやや基本的で不変です)。

正規化

3人のデータベース設計者が正規化されたデータベーススキーマを設計する場合、それらは同じ設計になります。わかりました、4NF/5NFのバリエーションはあるかもしれませんが、それほどではありません。さらに、デザイナーがモデルを検証するために尋ねることができる一連の質問があるので、デザイナーは4NFに到達したと確信できます(私は楽観的すぎますか?人々は4NFに到達するのに苦労していますか?)。

update:By4NFここでは、スキーマ内のすべてのテーブルが最大4NFまでの通常の形式(すべてのテーブルは最大4NFまで適切に正規化されます)。

正規化設計プロセスが、データベース設計者が一般的に正規化されたデータベーススキーマに依存するという考えに慣れている理由だと思います。

正規化のプロセスにより、DB設計は既知の「正しい」設計になり、そこからのバリエーションはパフォーマンスの非正規化になるはずです。

  1. サポートされているDBタイプに基づいてバリエーションがある場合があります(JSON、ARRAY、Geoタイプのサポートなど)
  2. 4NF/5NFに基づいた変動を主張する人もいます
  3. 物理的な変動は除外します(それは問題ではないため)
  4. これをOLTP設計に制限します。DW設計ではありません。これらは読み取り専用アクセス権を付与するスキーマであるためです。

3人のプログラマが(コードとして)実装する設計を与えられた場合、予想は3つの異なる実装(潜在的に非常に異なる)になります。

私には「正規化への信仰」の問題が潜在的にあります。

スキーマの変更に違反していますか?

非正規化、列の追加、より大きなストレージのための列の変更、新しいテーブルでの設計の拡張などはすべて互換性のある変更であり、第4正規形になったDB設計者はそれを確信します。

破壊的な変更は、列/テーブルを削除するか、破壊的なタイプを変更することで明らかに可能です。可能ですが、実際には、私はここでまったく問題を経験していません。おそらく、重大な変更が何であるかが理解され、これらが適切に管理されているためでしょうか?

共有の読み取り専用スキーマのコンテキストでスキーマの変更を壊すケースを知りたいです。

マイクロサービスのより重要で重要なものは何ですか?そのAPIまたはそのデータベーススキーマ?それは他の世界との契約だからです。

私はこの声明に同意しますが、エンタープライズアーキテクトから「データは永遠に存続する」との重要な警告があると思います。つまり、APIは最も重要なことかもしれませんが、データは企業全体にとってもかなり重要であり、非常に長期間にわたって重要になります。

たとえば、Data WarehouseforBusiness Intelligence次に、APIに関係なく、スキーマとCDCサポートがビジネスレポートの観点から重要になります。

APIの問題?

APIが完璧で簡単である場合、ローカルの読み取り専用アクセスではなく常にAPIを選択するため、すべてのポイントは意味がありません。したがって、ローカルの読み取り専用アクセスを検討する動機は、ローカルアクセスが回避するAPIの使用に問題がある可能性があることです。

What motivates people to desire local read-only access?

APIの最適化:

LinkedInは、APIの最適化の問題と、その規模で彼らにとってなぜ重要なのかについて(2009年から)興味深いプレゼンテーションを行っています。 http://www.slideshare.net/linkedin/building-consistent-restful-apis-in-a-highperformance-environment

つまり、APIが多くの異なるユースケースをサポートする必要がある場合、ネットワークの観点とデータベースの観点からは、1つのユースケースを最適にサポートし、残りのユースケースを不十分にサポートする状況に簡単に陥ってしまいます。

APIがLinkedInと同じように洗練されていない場合は、以下のシナリオを簡単に取得できます。

  • APIは必要以上のデータをフェッチします(無駄)
  • APIを何度も呼び出さなければならないChatty API

はい、もちろんAPIにキャッシングを追加できますが、最終的にAPI呼び出しはリモート呼び出しであり、データがローカルの場合、開発者は一連の最適化を利用できます。

私はそれを次のように追加するかもしれない人々のセットがそこにいると思います:

  • マスターデータをマイクロサービスデータベースに低コストで複製(開発コストなし、技術的に効率的)
  • 正規化への信仰とスキーマの変更に対するアプリケーションの回復力
  • すべてのユースケースを簡単に最適化し、おしゃべり/無駄/非効率的なリモートAPI呼び出しを回避する機能
  • 加えて、制約と一貫性のある設計に関する他のいくつかの利点

この回答は長すぎます。謝罪!!

4
Rob Bygrave

状態管理(場合によってはデータベース)をマイクロサービスのコンテナーにデプロイし、APIを介して公開できます。マイクロサービスのデータベースは、コンテナ外の他のシステムからは見えません。APIだけが見えます。または、APIを介して別のサービス(キャッシュなど)で状態を管理することもできます。単一のデプロイ可能なコンテナー内にすべてのマイクロサービスの依存関係(他のサービスへのAPI呼び出し以外)があることは、アーキテクチャーの重要な違いです。それが得られない場合は、戻ってアーキテクチャを調べてください。

0
Eric Roch