最も単純なマイクロサービスの設計でさえ、データの重複や共有データベースを回避するのが難しいと感じているため、何かが足りないと思っています。これが私が直面している問題の基本的な例です。誰かがWebアプリケーションを使用して在庫を管理しているとすると、2つのサービスが必要になります。 1つは、アイテムと在庫の数量を管理する在庫、およびユーザーデータを管理するユーザーサービス用です。誰がデータベースをストックしたかについての監査が必要な場合は、在庫サービスのデータベースにユーザーIDを値による最後のストックとして追加できます。
アプリケーションを使用して、残り少なくなっているすべてのアイテムと、前回それらをストックした人のリストを表示して、アイテムの再補充を依頼できるようにすることができます。上記のアーキテクチャを使用して、在庫サービスに対して、数量が5未満のすべてのアイテムのアイテム詳細を取得するように要求が行われます。これにより、ユーザーIDを含むリストが返されます。次に、インベントリサービスから取得したユーザーIDのリストのユーザー名と連絡先の詳細を取得するために、ユーザーサービスに対して別の要求が行われます。
これはひどく非効率的で、異なるサービスAPIに複数のリクエストを行い、次に複数のデータベースクエリを作成する前に、さらに多くのサービスを必要としません。別の方法は、インベントリデータのユーザー詳細を複製することです。ユーザーが連絡先の詳細を変更した場合、他のすべてのサービスを通じて変更を複製する必要があります。しかし、これはマイクロサービスの制限されたコンテキストのアイデアに適合しないようです。単一のデータベースを使用して、これを異なるサービス間で共有することもできます そして統合データベースのすべての問題があります 。
これを実装するための正しい/最良の方法は何ですか?
複製が必要な場所を完全に逃しました。
マイクロサービスの中心的な原則は、サービスが単一の権限であることです。つまり、インベントリとユーザー管理を完全に分離することができます。私は、在庫管理システムが存在することさえ知らないようにユーザー管理を設計します。
ただし、ユーザーID以外のユーザーについては何も保存しないように在庫システムを設計します。これで、ユーザー情報の変更を伝播する問題が解決します。
ログ、監査、印刷など、インベントリ情報とユーザー情報の両方が必要なものについては、情報が変更されても更新されません。彼らは何だったかの記録です。繰り返しますが、変更を伝播しません。
したがって、どの場合でも、最新のユーザー情報が必要な場合は、ユーザー情報サービスに問い合わせます。
データの重複を避けるのは難しいと思います...
マイクロサービスアーキテクチャに関するMicrosoft電子ブック によると、データの複製に問題はありません。基本的に、データを複製するとサービス間のデカップリングが増加するため、単一の権限としての役割が強化されます。関連する文章:
最後に(そしてこれがマイクロサービスの構築時にほとんどの問題が発生する場所です)、最初のマイクロサービスが他のマイクロサービスが元々所有していたデータを必要とする場合、そのデータに対して同期リクエストを行うことに依存しないでください。代わりに、replicateまたは結果整合性を使用して(通常は統合イベントを使用して)そのデータ(必要な属性のみ)を初期サービスのデータベースに伝播します...
在庫サービスに対して、数量が5未満のすべてのアイテムのアイテム詳細を取得するように要求が出されます。これにより、ユーザーIDを含むリストが返されます。次に、インベントリサービスから取得したユーザーIDのリストのユーザー名と連絡先の詳細を取得するために、ユーザーサービスに対して別の要求が行われます。
確かにそう。
確かに、モノリスでは、関連するアイテムを照会するインベントリモデルを作成し、それをユーザーモデルにフィードして同じデータを取得できます。
または、それをさらに進めることもできます。同じリレーショナルデータベースにそれらがあり、SQLを記述すれば、データベースが在庫表とユーザー表を取得し、いくらか魔法をかけ、目的のデータを取得します。
方法に関係なく、どこかにどこかにインベントリシステムからユーザーIDのリストをフェッチし、それらをユーザーシステムにフィードし、データのリストをコンパイルします。
答える必要がある質問は、パフォーマンスとメンテナンス、およびその他の「ソフト」品質についてです。
マイクロサービスの主な利点はスケーリングです。 1台のマシンに1万人のユーザーがいて、少し遅い場合は、別のマシンを追加すると、システムが2倍の速度になります。さらに8を追加すると、10倍の速度になります。 (線形スケーリングはおそらく楽観的ですが、理想的でありそれではありません期待するのは無理です。)
そして、これはserviceごとです。インベントリシステムがボトルネックである場合、それはユーザーに関するレポート以外にも使用されます。そのサービスだけにマシンを追加できます。機械は専門化することもできます。このサービスは大量のメモリを必要とし、そのサービスは重い計算を行い、より多くのCPUを必要とします。
スケーリングが必要ない場合は、マイクロサービスのもう1つの利点があります:これらはモジュール化されています。もちろん、モノリシックアプリはモジュール化することもできます。正規化されたデータベースなどがありますが、実際には、モジュール間の壁は最良の場合はガラスの壁、最悪の場合は砂の線のようなものです。マイクロサービスは、固体鋼で分離されています。
ユーザーシステムが文字どおり火災を起こしたとしても、在庫システムにはほとんど影響しません。あなたは誰が何をストックしたかについてのきれいなレポートを印刷することはできませんが、顧客はストックされたアイテムがそこにあるという知識で安全に注文することができます。
そして、あなたはマイクロサービスのデータを複製しないでくださいであり、リレーショナルデータベース(*)で行うよりも多くなります。リレーショナルデータベースでは、joinを実行できます。これに相当するのは、説明のようにコードでリストをマージすることです。
viewを追加することもできます。これは、マージを行う新しいサービスを追加することと同じです。その結果、3つのリクエストが発生します。 1つは新しいサービスに、次にそのサービスは元の2つを行います。リレーショナルデータベースには、サービスレベルで実装する必要のある、ビューを最適化する豪華な機能があります。 「無料」で入手することはできません。
キャッシュはデータの複製とは異なり、2つの値が一致しない場合、どちらが間違っているかがわかります。マイクロサービスでは、一貫性を犠牲にしてavailabilityを上げるためによく使用されます(CAPの定理)。リレーショナルデータベースは整合性の祭壇で完全に肉屋の可用性を提供するため、それらのデータベースではあまり一般的ではありません。マイクロサービスにはキャッシングを容易にする固有のものは何もないと私は思いますが、実際にはキャッシングが第一の関心事であり、それがマイクロサービスでのキャッシングを容易にするになります。
(*)マイクロサービスの群れでデータを複製することが理にかなっている場合、同等のリレーショナルデータベースでおそらく意味があります。