モノリスからマイクロサービスに移行するときに外部キーの制約を処理する方法は?


18

私のチームは、モノリシックASP.NETアプリケーションから.NET CoreおよびKubernetesに移行しています。コードの変更は予想通りに進行しているように見えますが、私のチームが多くの不一致に遭遇しているのはデータベースの周辺です。

現在、ビジネス全体のすべてのデータを格納するかなり大きなSQL Serverデータベースがあります。私は、コードを分割するのと同様の方法でデータベースを分割することを提案しています-1つの(論理)データベースのカタログデータ、別のデータベースの在庫データ、別の注文など-そして各マイクロサービスはそのデータベースのゲートキーパーになるでしょう。

ここでの意味は、マイクロサービスの境界を越える外部キーを削除する必要があり、境界を越えて到達するprocsおよびビューは禁止されることです。すべてのデータモデルは同じ物理データベースに存在する場合と存在しない場合がありますが、存在する場合でも、相互に直接対話することはできません。注文は引き続きIDでカタログアイテムを参照しますが、データベースレベルでデータの整合性が厳密に強制されることはなく、そのデータはSQLではなくコードで結合する必要があります。

これらの損失は、マイクロサービスへの移行と、それに伴うスケーラビリティのメリットを得るための必要なトレードオフと考えています。縫い目を賢く選択し、それらの周りに展開する限り、問題ありません。他のチームメンバーは、すべてが同じモノリシックデータベースにとどまる必要があるため、すべてがACIDであり、参照整合性をどこにでも保持できることを固く主張しています。

これは私の質問に私をもたらします。まず、外部キーの制約と参加に対する私の姿勢はもっともらしいですか?もしそうなら、誰かが私が同僚に提供できる信頼できる読み物を知っていますか?彼らの立場はほとんど宗教的であり、彼らはマーティン・ファウラー自身が彼らが間違っていると告げる以外に何かに左右されることはないようです。


5
参照整合性は非常に重要です。データベースの規模は本当にボトルネックですか?マイクロサービススタイルのスケーラビリティが本当に必要ですか?そのアーキテクチャの変更が組織に適しているかどうかは、私よりもよく知っていますが、多くのユースケースに適したものではないことを考慮してください。より魅力的なトレードオフでスケーリングする他の方法があるかもしれません。たとえば、1秒あたりのデータベースクエリが高すぎる場合、データベースレプリケーションだけで十分な場合があります。また、マイクロサービスを使用せずにWebサーバーを水平方向に拡張できます。
アモン

良い点。短期的な利益のためにこれらのオプションのいくつかを検討しています。ただし、マイクロサービスへの移行は長期にわたるものです。私の意見では、これにより数か月ではなく数年の拡張が可能になります。
レイモンドサルトレリ

3
在庫が1つしかなかったときに他の人が同じ製品を注文したため、0.05ms早く注文した注文がキャンセルされることに興奮していることを確信しています。
アンディ

@amonこれを答えにして、それを支持します。これは良い質問であり、賛否両論を公平に表現する必要があります。
mcottle

@mcottle OK、できました!
アモン

回答:


19

明確な解決策はありません。これは、コンテキストに完全に依存するためです。特に、システムがどの次元にスケーリングされるべきか、実際の問題は何かに依存します。データベースは本当にあなたのボトルネックですか?

この(残念ながらかなり長い)答えは、「マイクロサービスは悪い、一生モノリス!」のようなものですが、それは私の意図ではありません。私のポイントは、マイクロサービスと分散データベースがさまざまな問題を解決できることですが、独自の問題がないわけではありません。アーキテクチャについて強力な議論を行うには、これらの問題が適用されず、軽減できること、およびこのアーキテクチャがビジネスニーズに最適な選択肢であることを示す必要があります。

分散データは困難です。

より優れたスケーリングを可能にする同じ柔軟性は、より弱い保証の裏返しです。特に、分散システムは推論するのがはるか困難です。

アトミックな更新、トランザクション、一貫性/参照整合性、および耐久性は非常に貴重であり、無意味に放棄すべきではありません。データが不完全、古くなっている、または完全に間違っている場合、データを持つことにはほとんど意味がありません。ビジネス要件としてACIDがあり、そのままでは提供できないデータベーステクノロジー(多くのNoSQLデータベース、またはDB-per-microserviceアーキテクチャなど)を使用している場合、アプリケーションはギャップを埋め、それらの保証を提供する必要があります

  • これは不可能ではありませんが、正しく行うのは難しいです。とてもトリッキーです。特に、各データベースに複数のライターが存在する分散設定では。この難しさは、おそらくドロップされたデータ、一貫性のないデータなどを含むバグの可能性が高いことを意味します。

    たとえば、Cassandra分析から始めて、有名な分散データベースシステムJepsen分析を読むことを検討してください。私はその分析の半分を理解していませんが、TL; DRは、分散システムは非常に困難であり、業界をリードするプロジェクトでさえ、後知恵で明らかなように誤解することがあります。

  • 分散システムは、より大きな開発努力も意味します。ある程度までは、開発コストとより強力なハードウェアでのお金の削減との間には直接的なトレードオフがあります。

例:ぶら下がり参照

実際には、コンピューターサイエンスではなく、ビジネス要件を確認して、ACIDを緩和できるかどうか、どのように緩和できるかを確認する必要があります。例えば、多くの外部キー関係は、見た目ほど重要ではないかもしれません。製品とカテゴリーn:mの関係を考えてください。RDBMSでは、外部キー制約を使用して、既存の製品と既存のカテゴリのみがその関係の一部となるようにします。製品とカテゴリのサービスを別々に導入し、製品またはカテゴリを削除するとどうなりますか?

この場合、それは大きな問題ではない可能性があり、アプリケーションを作成して、存在しない製品またはカテゴリを除外することができます。しかし、トレードオフがあります!

  • これにはJOIN、データベースサーバーからアプリケーションに処理を移動するだけの、複数のデータベース/マイクロサービス上のアプリケーションレベルが必要になる場合があることに注意してください。これにより総負荷が増加し、ネットワークを介して余分なデータを移動する必要があります。

  • これはページネーションを混乱させる可能性があります。たとえば、カテゴリから次の25製品を要求し、その応答から使用できない製品を除外します。これで、アプリケーションに23の製品が表示されます。理論的には、製品がゼロのページも可能です。

  • 関連する各変更の後、または定期的に、ぶら下がり参照をクリーンアップするスクリプトを時々実行する必要があります。このようなスクリプトは、バッキングデータベース/マイクロサービスにすべての製品/カテゴリを要求して、それがまだ存在するかどうかを確認する必要があるため、かなり高価であることに注意してください。

  • これは明らかなはずですが、明確にするために、IDを再利用しないでください。自動インクリメントスタイルのIDは、問題がある場合とない場合があります。GUIDまたはハッシュは、たとえば、アイテムがデータベースに挿入される前にIDを割り当てることができるなど、柔軟性を高めます。

例:同時注文

代わりに、製品と注文の関係を検討してください。製品が削除または変更された場合、注文はどうなりますか?わかりました。簡単に関連する製品データを注文エントリにコピーして、利用可能な状態に保つことができます。簡単にするためにディスクスペースを取引します。しかし、製品の価格が変更されたり、その製品の注文が行われる直前に製品が利用できなくなったりした場合はどうなりますか?分散システムでは、効果が伝播するのに時間がかかり、古いデータで順序が変わる可能性があります。

繰り返しますが、これにアプローチする方法は、ビジネス要件によって異なります。期限切れの注文は受け入れられる可能性があり、注文が履行できない場合は後でキャンセルできます。

しかし、それはオプションではないかもしれません。例えば、高度な同時設定の場合です。3000人が最初の10秒以内にコンサートチケットを買いに急いでいると考えてください。最後のチケットを複数の人に販売する確率はどのくらいですか?これらの衝突がどのように扱われるかに依存しますが、とポアソン分布を使用してλ = 3000 / (10s / 10ms) = 3、我々が得るP(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%10msの間隔あたりの衝突の可能性を。不正行為を行わずに注文の大部分を販売し、後でキャンセルできるかどうかは、法務部門との興味深い会話につながる可能性があります。

プラグマティズムとは、最高の機能を選りすぐることを意味します。

幸いなことに、そうでない場合は、分散データベースモデルに移行する必要はありません。「適切に」マイクロサービスを行わない場合、マイクロサービスクラブの会員資格を取り消すことはできません。そのようなクラブは存在せず、マイクロサービスを構築する真の方法もないからです。

プラグマティズムは毎回勝つため、問題を解決するためにさまざまなアプローチを組み合わせて組み合わせてください。これは、一元化されたデータベースを持つマイクロサービスを意味する場合もあります。本当に、必要がなければ分散データベースの苦痛を経験しないでください。

マイクロサービスなしでスケーリングできます。

マイクロサービスには2つの大きな利点があります。

  • 別々のチームが独自に開発および展開できるという組織上の利点(サービスが安定したインターフェイスを提供する必要があります)。
  • 各マイクロサービスを個別にスケーリングできる運用上の利点。

独立したスケーリングが必要ない場合、マイクロサービスはあまり魅力的ではありません。

データベースサーバーは、既にリードレプリカを追加するなどして、独立して(ある程度)拡張できるサービスの一種です。ストアドプロシージャに言及します。それらを減らすと、他のスケーラビリティの議論が意味をなさないほど大きな影響を与える可能性があります。

そして、すべてのサービスをライブラリーとして含むスケーラブルなモノリスを持つことは完全に可能です。その後、モノリスのインスタンスをさらに起動することでスケーリングできます。もちろん、各インスタンスをステートレスにする必要があります。

これは、モノリスが大きすぎて合理的に展開できない場合、または一部のサービスに特別なリソース要件があるため、それらを個別にスケーリングする必要がある場合にうまく機能する傾向があります。追加のリソースが関係する問題ドメインには、個別のデータモデルが関係しない場合があります。

強力なビジネスケースはありますか?

組織のビジネスニーズを認識しているため、分析に基づいて、マイクロサービスごとのデータベースアーキテクチャの引数を作成できます。

  • 特定の規模が必要であり、このアーキテクチャは、そのようなセットアップおよび代替ソリューションの開発努力の増加を考慮して、そのスケーラビリティを得るための最も費用対効果の高いアプローチです。そして
  • 上記のようなさまざまな問題を引き起こすことなく、ビジネス要件により関連するACID保証を緩和できること。

逆に、これを実証できない場合、特に現在のデータベース設計が将来に十分な規模をサポートできる場合(同僚が信じているように思われる場合)、答えもあります。

また、スケーラビリティに大きなYAGNIコンポーネントがあります。不確実性に直面している場合、これはスケーラビリティの構築に関する戦略的なビジネス上の決定です(総コストは低くなりますが、機会コストが含まれ、必要ではない場合があります)スケーラビリティに関する作業を延期します(必要に応じて総コストが高くなりますが、実際のスケールのアイデア)。これは主に技術的な決定ではありません。


素晴らしい答え、ありがとう。この声明について詳しく説明していただけますか?プロシージャの数を減らすと、パフォーマンスに大きな影響が出る可能性がありますか?ストアドプロシージャに言及します。それらを減らすと、他のスケーラビリティの議論が意味をなさないほど大きな影響を与える可能性があります。
アラン

1
@alanストアドプロシージャは良い目的で使用できますが、2つのパフォーマンス上の問題が発生します。(1)データベースが最適化するのがより複雑なクエリは困難です。(2)sprocsを使用すると、DBサーバーでより多くの作業を行うことができます。OPは、さらに拡張するためにDBを分割したいと考えていますが、複雑なsprocを回避することで、すでにその余裕を提供できます。もちろん、クエリ応答のためにDBから転送する必要があるデータの量を最小化する場合など、sprocsおよび複雑なクエリもパフォーマンスに適しています。DBを分割すると、クロスサーバーJOINが必要な場合にその問題が悪化します。
アモン

0

私は両方のアプローチがもっともらしいと信じています。ACIDおよびモノリシックデータベースの利点を犠牲にしてスケーラビリティを獲得し、現在のアーキテクチャを維持し、より分散されたアーキテクチャのスケーラビリティと俊敏性を犠牲にすることを選択できます。正しい決定は、今後数年間の現在のビジネスモデルと戦略から導き出されます。純粋にテクノロジーの観点から見ると、モノリシックな状態を維持するだけでなく、より分散されたアプローチに移行するという苦労もあります。システムを分析し、モノリシックアーキテクチャで待機または継続する必要があるものを決定するために、どのアプリケーション/モジュール/ビジネスプロセスがスケーリング、リスク、コスト、および利点を評価するためにより重要であるかを確認します。


-1

あなたのスタンスはもっともらしく正しい。

ウールdbの常習者に染めた説得方法は別の質問です。2つの選択肢があると思います。

  1. DBがその限界に達した具体的な例を見つけます。たとえば、「アーカイブテーブル」はありますか?なぜ大丈夫ですか?1秒あたりの最大注文数はいくらですか?など。DBが要件を満たしていないことを示し、ソリューションで要件を修正します。

  2. 高価な請負業者を雇って、最適なソリューションを教えてください。彼らは費用がかかり、ブログを持っているので、誰もがそれらを信じます


1
私は-1ではありませんが、これが良い答えになるには、ポイント2のスナークを失い、複数のデータベースを必要とすることが適切になる時期を拡大します。アーカイブテーブルは、必ずしもパーティション分割をサポートしていないデータベースのアンチパターンとは思わない。現在使用しているデータベースには、130 MBを超えるデータがあり、26のテーブルで1,000万行を超える行があり、データベースを分割する必要があるほどパフォーマンスがリモートで十分ではありません。だから私は非常に懐疑的であり、なぜこれが良いアイデアであり、それを行う必要があるとき、この答えが私がこれまで見た中で最も近いです。
mcottle

上手。アーカイブテーブルについては、FKの制約を覆い隠すので言及します。その装甲の隙間。マイクロサービスで分割することは、dbのサイズではなく、マイクロサービスを分離可能なものにすることです。1つをオフにして破棄できない場合、それは実際にはマイクロサービスではありません。re point 2. OPがMFに言及している場合、文字通り彼/ thoughtworksを雇い、dbを分割するよう指示することができます
Ewan

「1つをオフにして捨てることができない場合、それは実際にはマイクロサービスではありません。」これはサービス自体にも当てはまりますが、必ずしもサービスが独自のデータベースを必要とする理由の議論ではありません。最終的に、データベース自体がマイクロサービスによって使用されるサービスです。マイクロサービスは、使用しているデータが別のデータベースにあるか、共有データベースにあるかを実際には知りません。このマイクロサービスのコピーを起動または停止できますが、実際には何も変わりません。
クリスプラット

データベースごとのサービスの最適な引数は接続制限です。接続プールが使用されることは珍しいことではないため、各マイクロサービスはデータベースインスタンスへの複数の接続を既に必要としているため、これらの各マイクロサービスの複数のインスタンスに独自のプールを持たせることができます。最終的には、データベースが取得しているすべての接続を処理するデータベースの機能を使い果たしてしまったという事態に直面する可能性があります。
クリスプラット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.