別のマイクロサービスによって「所有」されているデータベースからデータを読み取ることがなぜそれほど悪いのか


64

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

AmazonにWebページをロードすると、100以上のマイクロサービスが協力してそのページを提供することが記載されています。

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

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

言うまでもなく、私の会社はAmazonよりもずっと小さく(常にそうです)、私たちが持つことのできるユーザーの最大数は約500万人です。


回答で言及されていないもう1つの一般的な要因は、データベースに書き込まれたときに、ローカルキャッシュ、単純なO / Rマッピングでさえ、データベースにすぐにアクセスするときに古いデータを生成する可能性があることです。速度の理由でµservice APIをバイパスすることを検討する場合、µserviceアーキテクチャを使いすぎた可能性があります。
ジョープエッ

データベースの読み取りを許可すると、データベースのすべての詳細がパブリックAPIの一部になります。このような複雑なAPIの互換性を維持したくありません。
パトリック14年

しかし、その場合、少なくとも意味的な目的のために、ビューは単にAPIの一部になりませんか?それはあなたがAPIを何を呼んでいるのか、そしてそれが何を維持せざるをえないのかという問題です。(通常、データベースの上の層は一貫性を保つのが簡単です。)
lc。

ビューは単にAPIの形式であることに同意します。この質問に答えるほとんどの人は、抽象化のレベルとしてビューを使用するという私の考えを読んでいないと思います。ただし、データベーステクノロジーを変更した場合にビューをそのまま維持することは大きな課題になることは理解していますが、今後5年間はデータベーステクノロジーを変更する必要はないと確信しています。また、わずか5ミルのユーザーでもパフォーマンスは問題になりません。ですから、ここでの答えは私が苦痛の世界にまっすぐに向かっていることを示しているように見えますが、サイズを考えると、この解決策に行くことに感謝します。
デビッド14年

回答:


69

データベースは情報の隠蔽があまり得意ではありません。実際には情報を公開するのが仕事なので、これは非常に妥当です。しかし、これにより、カプセル化に関してはお粗末なツールとなります。カプセル化が必要な理由

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

ストレージ層をアプリケーション層から直接手探りすることは、依存関係反転の原則が示唆することとは正反対です。


1
これは素晴らしい点です!私が心配することの1つは、PostgresがドキュメントストアとRDBMSの両方をサポートするようになったことです(withouttheloop.com/articles/2014-09-30-postgresql-nosql)。ただし、あなたの主張はまだ有効であり、慎重に検討します。
デビッド14年

3
ツールが何かをすることができるからといって、@ Davidの心配を減らす必要はありません。それがある程度の分離を持っていることのポイントです-ユーザーが見るものを変えることなく、APIの背後にあるデータを完全に変えることができます。私はここでデータベース担当者として話しています...クライアントが見るものが同じである限り、あなたが望むだけバックエンドを変更できます。
ベン14年

1
@Davidこれは興味深いニュースですが、説明したシナリオにはまったく関係ありません。DBスキーマをリレーショナルスキーマからドキュメントベースのスキーマに変更すると、それに依存するすべてのスキーマに同じ影響があります。すべてのクエリを書き換える必要があります。コンポーネント間の互換性がシステム全体で維持されるように、これらすべての変更を一度に展開する必要があるという悪夢もあります。
back2dos 14年

1
@David:いくつかの明確に定義されたビューへのアクセスを制限することは、おそらく、別のAPIを構築することを意味し、それに付随する利点もいくつかあります。ただし、表示のみである限り、読み取り専用アクセスに制限されます。また、コンポーネントはサービスAPIとビューAPIの両方に依存しているため、非常に脆弱です。そのため、ビューに依存するコンポーネントを作成している場合、読み取り専用または高メンテナンスになるように事前に決めています。ここで技術的負債の臭いがします。また、データベースで許可されていない方法で水平分割を追加することもできます。
back2dos 14年

2
@David:長い目で見れば、コードを書くのがどれほど簡単かよりも、コードを変更するのがどれほど簡単かが重要です。アーキテクチャは「そのような方法でコードを書くべきではありません」とは言いません。「そうすれば、それを維持しようとする恐ろしい悪夢に苦しむでしょう」と言います。プロトタイプについて話している場合、メンテナンスは必要ありません。どうぞ。プロトタイプは、できるだけ簡単にポイントを証明する必要があります。しかし、システムをSisypheanの自己誘発的拷問に委ねることなく、実証済みのすべてのポイントをシステムに統合しようとするときは、もう1マイルをかけたほうがよいでしょう。
back2dos

55

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

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

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

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

経験の浅い開発者(または学習していない開発者)は、データベースをサービスよりも重要であると見なし、データベースを本物であり、サービスを単に取得する方法と見なすのが一般的です。それは間違った方法です。


4
プロジェクト全体で作業している唯一の開発者であっても、上記の点はすべて有効です。複雑なプロジェクトを自分で管理することは、これらすべての懸念を引き起こします。
itsbruce 14年

15

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

コンポーネントのビジネスドメイン外のデータベースへの書き込み、さらにはデータベースからの読み取りさえも、このスタイルのアーキテクチャに反しています。

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

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

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

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


4

過去20年にわたって、いくつかの大規模なモジュラーデータベース設計を見てきました。また、アプリケーションが独自のスキーマ/テーブルセットへの書き込みアクセスと、別のスキーマ/テーブルのセット。ほとんどの場合、アプリケーション/モジュールが読み取り専用アクセスを取得するこのデータは、「マスターデータ」と呼ばれます

その間、以前の回答で見たはずの問題が見られなかったので、以前の回答で指摘されたポイントをより詳しく見る価値があると思います。

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

これは、マイクロサービスが読み取るためのデータのコピーをローカルに保持するための引数でもあることを除き、このコメントに同意します。つまり、ほとんどの成熟したデータベースは複製サポートしているため、開発者の努力なしに、「マスターデータ」をマイクロサービスデータベースに物理的に複製することができます。

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

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

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

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

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

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

スキーマの依存関係:

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

マスターデータ

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

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

正規化

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

更新:によって4NFここで私は、スキーマ内のすべてのテーブルは、(すべてのテーブルが4NFまで適切に正規化されてしまった)4NFまでの彼らの最高の正常な形になったわけ。

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

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

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

3人のプログラマーが(コードとして)実装するデザインを与えられた場合、3つの異なる実装(潜在的に非常に異なる)が期待されます。

私には、「正規化への信仰」という疑問が潜在的にあります。

スキーマの変更を壊しますか?

非正規化、列の追加、より大きなストレージ用の列の変更、新しいテーブルでの設計の拡張などはすべて非破壊的な変更であり、第4正規形に到達したDBデザイナーはそれを確信します。

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

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

マイクロサービスについてより重要で重要なものは何ですか:APIまたはデータベーススキーマですか?API。これは、他の世界との契約であるためです。

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

たとえば、ビジネスインテリジェンスのデータウェアハウスデータを入力する必要がある場合、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呼び出しを潜在的に回避する機能
  • さらに、制約と一貫性のある設計に関する他のいくつかの利点

この答えは長すぎます。おApび!!


通常、列を追加するとアプリケーションが破損します。「salary」がある場合、新しい列「salary_currency」が導入されると、すべての給与を合計するアプリケーションが中断します。
クバンチク

本当に?「ブレーク」の定義に依存します。「salary_currency」なしでアプリが本番環境にあり、期待どおりに動作している場合、なぜそのアプリケーションが壊れていると考えますか?
ロブBygrave

アプリケーションはエラーなしで実行され、いくつかの番号が表示されます。しかし、それは役に立たない。CEOが先月の給与の合計が5万ではなく6百万であると判断した場合(韓国ウォンで支払われる新入社員が1人いるため)、有用/役に立たない出力の定義についてはあまり議論されません。
クバンチク

0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.