[解決済み] マイクロサービスパターンでデータ非正規化はどのように機能するか?
質問
私はちょうど次の記事を読みました。 マイクロサービスとPaaSのアーキテクチャ . その記事の中で、3分の1くらいのところで、著者は次のように述べています (以下 狂ったように非正規化する ):
データベーススキーマをリファクタリングし、すべてを非正規化し、データの完全な分離とパーティショニングを可能にします。つまり、複数のマイクロサービスに対応する基礎となるテーブルを使用しないことです。複数のマイクロサービスにまたがる基礎となるテーブルを共有してはいけませんし、データの共有もしてはいけません。その代わり、複数のサービスが同じデータにアクセスする必要がある場合、サービスAPI(公開されたRESTやメッセージサービスインターフェースなど)を介して共有する必要があります。
一方、この が聞こえる 理論的には素晴らしいことですが、現実的には克服すべき重大なハードルがあります。その最大のものは、多くの場合、データベースは密結合で、すべてのテーブルが いくつかの という外部キー関係を持っていることです。このため、データベースの分割が不可能になることがあります。 n によって制御されるサブデータベース n マイクロサービスによって制御されます。
だから聞くのです。 関連するテーブルだけで構成されるデータベースがあるとして、これをより小さなフラグメント(テーブルのグループ)に非正規化し、フラグメントを別々のマイクロサービスによって制御できるようにするにはどうすればよいでしょうか?
例えば、次のような(かなり小さいですが、模範的な)データベースがあったとします。
[users] table
=============
user_id
user_first_name
user_last_name
user_email
[products] table
================
product_id
product_name
product_description
product_unit_price
[orders] table
==============
order_id
order_datetime
user_id
[products_x_orders] table (for line items in the order)
=======================================================
products_x_orders_id
product_id
order_id
quantity_ordered
私のデザインを批評するのにあまり時間をかけないでください。ポイントは、私にとって、このデータベースを3つのマイクロサービスに分割することが論理的に理にかなっているということです。
-
UserService
- システム内でユーザを CRUD するためのもので、最終的には[users]
テーブルを管理します。 -
ProductService
- を管理する必要があります。[products]
テーブルを管理します。 -
OrderService
- を管理する必要があります。[orders]
と[products_x_orders]
テーブル
しかし、これらのテーブルはすべて、互いに外部キーの関係を持っています。これらを非正規化し、モノリスとして扱うと、意味上の意味をすべて失ってしまいます。
[users] table
=============
user_id
user_first_name
user_last_name
user_email
[products] table
================
product_id
product_name
product_description
product_unit_price
[orders] table
==============
order_id
order_datetime
[products_x_orders] table (for line items in the order)
=======================================================
products_x_orders_id
quantity_ordered
これで、誰がいつ、何を、どれだけ注文したのか、知るすべはありません。
この記事は典型的な学術的騒ぎなのでしょうか、それともこの非正規化のアプローチには現実世界での実用性があるのでしょうか、あるとすればそれはどのようなものでしょうか(回答で私の例を使用するとボーナスポイントがつきます)。
どのように解決するのですか?
これは主観的なものですが、次の解決策は、私、私のチーム、そして私たちのDBチームにとってうまくいったものです。
-
アプリケーション層では、Microservicesはセマンティック機能に分解されます。
-
例えば
Contact
サービスは連絡先 (連絡先に関するメタデータ: 名前、電話番号、連絡先情報など) を CRUD するかもしれません。 -
例えば
User
サービスは、ログイン資格、認可ロールなどを持つユーザーを CRUD するかもしれません。 -
例えば
Payment
サービスは、決済を CRUD して、Stripe などのサードパーティの PCI 準拠のサービスと連携するかもしれません。
-
例えば
- DBレイヤーでは、開発者/DB/Devopsの人々が望むようにテーブルを編成することができます。
問題は、カスケード接続とサービス境界です。支払いは、誰が支払いを行っているのかを知るためにユーザーを必要とするかもしれません。このようにサービスをモデル化するのではなく
interface PaymentService {
PaymentInfo makePayment(User user, Payment payment);
}
このようにモデル化します。
interface PaymentService {
PaymentInfo makePayment(Long userId, Payment payment);
}
こうすることで、他のマイクロサービスのみに属するエンティティは を参照します。 オブジェクトの参照ではなく、IDによって特定のサービス内部で参照されます。これにより、DBテーブルは至る所で外部キーを持つことができますが、アプリレイヤーではquot;foreign"エンティティ(つまり、他のサービスに住むエンティティ)はIDを介して利用可能です。これにより、オブジェクトのカスケードが制御不能になるのを防ぎ、サービスの境界をきれいに区切ることができます。
それがもたらす問題は、より多くのネットワークコールを必要とすることです。たとえば、もし私が各
Payment
エンティティ a
User
を参照することで、一回の呼び出しで特定の支払いに対するユーザーを取得することができました。
User user = paymentService.getUserForPayment(payment);
しかし、ここで提案するものを使うと、2つの呼び出しが必要になります。
Long userId = paymentService.getPayment(payment).getUserId();
User user = userService.getUserById(userId);
これは破談になるかもしれません。しかし、もしあなたが賢く、キャッシュを実装し、各呼び出しが50~100ミリ秒で応答するようにうまく設計されたマイクロサービスを実装すれば、これらの余分なネットワーク呼び出しは、間違いなく ではなく アプリケーションにレイテンシーを発生させないように細工できることは間違いありません。
関連
-
[解決済み] ATTACHで開いたSQLiteデータベースファイルのテーブルを一覧表示するにはどうすればよいですか?
-
[解決済み】マイクロサービスアーキテクチャでGraphQLを使用するタイミングと方法
-
[解決済み] マスター・マスターとマスター・スレーブ、どちらのデータベース・アーキテクチャが良いのか?
-
[解決済み] SQLite UPSERT / UPDATE OR INSERT
-
[解決済み] リレーショナル・データベースにおけるカタログとスキーマの違いは何ですか?
-
[解決済み] SQLITE SQLダンプファイルをPOSTGRESQLに変換する
-
[解決済み] 非リレーショナルデータベース設計【終了しました
-
[解決済み] データベースとファイルシステムストレージ
-
[解決済み] 正規化された電話番号をデータベースに格納するための規格はありますか?
-
[解決済み] なぜデータベースは常に円柱で表現されるのですか?[クローズド]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] DBに型を格納する際のMIMETypeの最大長について
-
[解決済み] 1対1の関係はどのようなときに使うべきですか?
-
[解決済み] Neo4jでデータベースを削除/作成する方法は?
-
[解決済み] データベースに登録する電子メールアドレスの最適な長さは?
-
[解決済み] ソース管理からどのようにデータベースを構築するべきか?
-
[解決済み] SQL Developerで新しい接続を追加する際にOracle TNSの名前が表示されない
-
[解決済み] なぜデータベースは常に円柱で表現されるのですか?[クローズド]
-
[解決済み] 営業時間のデータベースへの格納
-
[解決済み] 人名と性別を対応させるのに適したライブラリをご存知の方はいらっしゃいませんか?[クローズド]
-
[解決済み] 破損したSQLite3データベースを復旧する方法