私のチームは、一体型のASP.NETアプリケーションから.NET CoreとKubernetesに移行しています。コードの変更は期待どおりに進んでいるように見えますが、私のチームが多くの不一致に遭遇しているのはデータベースの周辺です。
私たちは現在、ビジネス全体のすべてのデータを格納するかなり大きなSQL Serverデータベースを持っています。コードを分割するのと同じような方法でデータベースを分割することを提案します-(1つの(論理)データベースのカタログデータ、別のデータベースの在庫データ、別の注文)など、各マイクロサービスはそのデータベースのゲートキーパーになります。
ここでの意味は、マイクロサービスの境界を越える外部キーを削除する必要があり、境界を越えて到達するsprocおよびビューは禁止されることです。すべてのデータモデルは同じ物理データベースに存在する場合と存在しない場合がありますが、存在する場合でも、相互に直接対話するべきではありません。注文は引き続きIdによってカタログアイテムを参照する可能性がありますが、データの整合性はデータベースレベルで厳密に適用されず、そのデータはSQLではなくコードで結合する必要があります。
これらの損失は、マイクロサービスへの移行とそれに付随するスケーラビリティのメリットを得るための必要なトレードオフとして見ています。縫い目を賢く選択し、それらの周りに発達する限り、問題はありません。他のチームメンバーは、すべてが同じモノリシックデータベースにとどまる必要があるため、すべてをACIDにして、参照整合性をどこにでも保持できるようにする必要があります。
これは私に私の質問をもたらします。最初に、外部キーの制約と参加への私のスタンスはもっともらしいですか?もしそうなら、誰かが私の同僚に提供できる信頼できる読み物を知っていますか?彼らの立場はほぼ宗教的であり、彼らはマーティン・ファウラー自身が彼らに間違っていると告げる以外には何にも動揺しないようです。
これは完全にコンテキストに依存するため、明確な解決策はありません。特に、システムがスケーリングすることになっているディメンションと実際の問題は何であるかによって異なります。データベースは本当にあなたのボトルネックですか?
この(残念ながらかなり長い)回答は、「マイクロサービスは良くない、一生モノです!」のように見えますが、それは私の意図ではありません。私の要点は、マイクロサービスと分散データベースはさまざまな問題を解決することができるということですが、それ自体にいくつかの問題がないわけではありません。アーキテクチャについて強力な議論をするためには、これらの問題が当てはまらないこと、緩和できること、およびこのアーキテクチャがビジネスニーズにとって最良の選択であることを示す必要があります。
より良いスケーリングを可能にするのと同じ柔軟性が、弱い保証の裏側です。特に、分散システムは推論するのがはるかにはるかに困難です。
アトミック更新、トランザクション、一貫性/参照整合性、および耐久性は非常に貴重であり、急いで放棄されるべきではありません。データが不完全、古くなっている、またはまったく間違っている場合は、データを持つことにほとんど意味がありません。 ACIDをビジネス要件として使用しているが、そのままでは提供できないデータベーステクノロジー(多くのNoSQLデータベース、またはDBごとのマイクロサービスアーキテクチャなど)を使用している場合、アプリケーションギャップを埋め、それらの保証を提供する必要があります。
これを行うのは不可能ではありませんが、正しく行うのが難しいです。とてもトリッキーです。特に、各データベースに複数のライターがある分散設定では。この問題は、データの欠落、データの不整合などを含む、バグが発生する可能性が高いことを意味します。
たとえば、おそらく Cassandraの分析 で始まる 有名な分散データベースシステムのJepsen分析 を読むことを検討してください。私はその分析の半分を理解していませんが、TL; DRは、分散システムは非常に困難であり、業界をリードするプロジェクトでさえ、後から明らかなように誤った方法で誤解することがあります。
分散システムはまた、より大きな開発努力を意味します。ある程度までは、開発コストとより強力なハードウェアへの投資との間には直接的なトレードオフがあります。
実際には、コンピュータサイエンスではなく、ビジネス要件を見て、ACIDを緩和できるかどうか、またどのように緩和できるかを確認する必要があります。例えば。多くの外部キー関係は、見かけほど重要ではない場合があります。製品とカテゴリn:mの関係を考えてみましょう。 RDBMSでは、既存の製品と既存のカテゴリのみがその関係の一部になることができるように、外部キー制約を使用する場合があります。別の製品とカテゴリのサービスを導入し、製品またはカテゴリを削除するとどうなりますか?
この場合、それは大きな問題ではない可能性があります。存在しない製品またはカテゴリをフィルターで除外するようにアプリケーションを作成できます。ただし、トレードオフがあります。
これには、複数のデータベース/マイクロサービスに対するアプリケーションレベルのJOIN
が必要になる場合があることに注意してください。これは、データベースサーバーからアプリケーションに処理を移動するだけです。これにより、総負荷が増加し、追加のデータをネットワーク経由で移動する必要があります。
これはページネーションを混乱させる可能性があります。例えば。カテゴリから次の25個の製品をリクエストし、そのレスポンスから利用できない製品を除外します。これで、アプリケーションに23の製品が表示されます。理論的には、製品がゼロのページも可能です。
関連する各変更の後または定期的に、ぶら下がっている参照をクリーンアップするスクリプトをときどき実行する必要があります。そのようなスクリプトは、それがまだ存在するかどうかを確認するために、バッキングデータベース/マイクロサービスからすべての製品/カテゴリを要求する必要があるため、かなり高価になることに注意してください。
これは明白ですが、明確にするために、IDを再利用しないでください。自動インクリメントスタイルのIDは問題ない場合があります。 GUIDまたはハッシュにより、柔軟性が向上します。アイテムがデータベースに挿入される前にIDを割り当てることができる。
代わりに、製品と注文の関係を考えてみましょう。製品が削除または変更された場合、注文はどうなりますか?わかりました。関連する製品データを注文エントリにコピーするだけで、使用可能に保つことができます。ディスク領域を単純化するために交換します。しかし、製品の価格が変更された場合や、製品の注文が行われる直前に製品が利用できなくなった場合はどうなりますか?分散システムでは、効果が伝播するのに時間がかかり、注文が古いデータで処理される可能性があります。
繰り返しますが、これにどのように取り組むかは、ビジネス要件によって異なります。おそらく、古い注文が受け入れ可能であり、それが満たされない場合は後で注文をキャンセルできます。
しかし、おそらくそれは選択肢ではありません。並行性の高い設定の場合。最初の10秒以内に急いでコンサートのチケットを購入しようとする3000人を考えてみましょう。可用性の変化が反映されるまでに10ミリ秒かかると仮定します。最後のチケットを複数の人に販売する確率はどれくらいですか?これらの衝突の処理方法によって異なりますが、λ = 3000 / (10s / 10ms) = 3
でポアソン分布を使用すると、10ミリ秒間隔で衝突する可能性がP(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%
になります。詐欺を犯さずに注文の大部分を販売し、後でキャンセルすることが可能かどうかは、法務部との興味深い会話につながる可能性があります。
良いニュースは、分散データベースモデルに移行する必要がないことです。マイクロサービスを「適切に」実行しないと、マイクロサービスクラブのメンバーシップが取り消されることはありません。これは、そのようなクラブがなく、マイクロサービスを構築するための真の方法がないためです。
プラグマティズムは常に勝つため、さまざまなアプローチを組み合わせて問題を解決します。これは、集中型データベースを備えたマイクロサービスを意味することさえあります。本当に、必要がなければ分散データベースの苦痛を経験しないでください。
マイクロサービスには2つの主要な利点があります。
独立したスケーリングが必要ない場合、マイクロサービスはそれほど魅力的ではありません。
データベースサーバーはすでに、(ある程度)独立してスケーリングできる一種のサービスです。リードレプリカを追加する。ストアドプロシージャについて言及している。それらを削減すると、他のスケーラビリティに関する議論が議論されるほど大きな影響を与える可能性があります。
また、すべてのサービスをライブラリとして含むスケーラブルなモノリスを作成することは完全に可能です。その後、モノリスのインスタンスをさらに起動することでスケーリングできます。もちろん、各インスタンスはステートレスである必要があります。
これは、モノリスが大きすぎて適度にデプロイできないまで、または一部のサービスに特別なリソース要件があるために個別にスケーリングする必要がある場合にうまく機能する傾向があります。追加のリソースを含む問題のドメインには、個別のデータモデルが含まれない場合があります。
組織のビジネスニーズを認識しているため、分析に基づいてマイクロサービスごとのデータベースアーキテクチャの引数を作成できます。
逆に、これを実証できない場合、特に現在のデータベース設計が将来に向けて十分な規模をサポートできる場合(同僚が信じているように)、答えもわかります。
スケーラビリティに大きなYAGNIコンポーネントもあります。不確実性に直面して、それはスケーラビリティの構築(総コストは低いが機会コストが含まれるため必要ない場合がある)とスケーラビリティに関する一部の作業の延期(必要に応じて総コストが高いが、より良い実際のスケールのアイデア)。これは主に技術的な決定ではありません。
どちらのアプローチももっともらしいと思います。 ACIDとモノリシックデータベースの利点を犠牲にしてスケーラビリティを獲得し、現在のアーキテクチャを維持して、より分散されたアーキテクチャのスケーラビリティと俊敏性を犠牲にすることを選択できます。正しい決定は、今後数年間の現在のビジネスモデルとBuz戦略に基づいて行われます。純粋にテクノロジーの観点から見ると、それをモノリシックに保つだけでなく、より分散されたアプローチに移行するのに苦労があります。私はシステムを分析し、モノリシックアーキテクチャで待機または続行する必要があるものを決定するためにリスク、コスト、および利点をスケーリングおよび評価するためにどのアプリケーション/モジュール/ビジネスプロセスがより重要であるかを確認します。