目次


マイクロサービスへのリファクタリング, 第 2 回

データを移行する際の考慮事項

従来型のミドルウェア・アーキテクチャーからマイクロサービスにデータを移行すべき場合、移行すべきでない場合

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: マイクロサービスへのリファクタリング, 第 2 回

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:マイクロサービスへのリファクタリング, 第 2 回

このシリーズの続きに乞うご期待。

このシリーズの第 1 回で、マイクロサービス・ベースの手法に合わせてコードをリファクタリングする主な理由と、その際の考慮事項を説明しました。第 1 回は、データの処理方法に関する課題を投げかけて締めくくりました。通常、大規模なエンタープライズ・アプリケーションにおいてはデータが最も厄介な問題になるため、掘り下げて調べる価値があります。

何よりもまず、実際にどのようなデータを保管しているのかを特定すること

アプリケーションの構造を調べてデータを管理する最善の手法を選ぶときには、多くの場合、最終的に 1 つの質問に行き着きます。それは、「データベース内に実際に保管しているデータは何か」というものです。

1990 年代の始めから、私はオブジェクト・リレーショナル・マッピング (ORM) フレームワークを構築、保守する企業を手伝って来ましたが、こうした企業が ORM フレームワークの意味を曲解していることは珍しくありません。企業が実際に保管しているデータがリレーショナル・データ・モデルに上手くマッピングしなかったことは何度もあります。そのような場合、データに合わせてリレーショナル・モデルを無理やり「ねじ曲げる」必要に迫られます。それどころか、コードをリレーショナル・データ・ストアに無理やり合わせるために、プログラムで複雑な手順を踏まなければならないこともありました。

今では複数の選択肢からパーシスタンスを選べる時代になっているので、かつての決定を再調査して、より有効な決定を下すことができます。これから具体的に、リレーショナル・モデルが最善の選択肢ではなかった 4 つの事例を見ていきましょう。その後、リレーショナル・モデルが最善の選択肢であった (そしてデータをリファクタリングすることが最善の選択肢ではなかった) 1 つの事例について考えます。

事例 1: Blob ストレージ

これまで、エンタープライズ・システムのパーシスタンス・コード全体を調べてみると、驚いたことに、実際にリレーショナル・データベースに保管されるのはシリアライズされた Java オブジェクトのバイナリー表現でしかなかったことは何度もあります。通常、チームは Java オブジェクトをリレーショナル・テーブルと列にマッピングする際の複雑さにお手上げだと諦めると、こうしたオブジェクトを「バイナリー・ラージ・オブジェクト (Blob)」列に保管します。Blob ストレージの欠点としては、当然、列単位のクエリーが不可能であること、処理に時間がかかることが挙げられます。さらに、Java オブジェクト自体の構造の変化に影響されやすいという欠点もあります。オブジェクトの構造が大幅に変更されると、それまでのデータが読み取り不可能になることさえあります。

アプリケーション (通常はアプリケーションのサブセット) でリレーショナル・データベース内の Blob ストレージを使用しているとしたら、それは、Key-Value 型ストア (Memcached や Redis など) を使ったほうが得策であることを示す確たる証拠となります。

一方、アプリケーションが構造化された Java オブジェクト (おそらくは深く構造化されているものの、本来はバイナリーではないオブジェクト) だけを保管している場合は、ドキュメント・ストア (CloudantMongoDB など) を使用するのが得策でしょう。さらに、ドキュメントを保管する仕組みに少々労力をつぎ込めば、ストレージ・メカニズムがかなり不明瞭な Blob ストアを扱う場合よりも、「スキーマ・ドリフト」の問題に対処するのがはるかに簡単になります (例えば、Cloudant データベースと MongoDB データベースはどちらも JSON ドキュメント・ストアです。JSON パーサーは広く利用できて、簡単にカスタマイズできます)。

事例 2: フラットなオブジェクトと Active Record パターン

数年前、Martin Fowler が『エンタープライズアプリケーションアーキテクチャパターン』を執筆しているときに、私たちは多くのパターンについて盛んに文書のやり取りを交わし、何回か対面でのレビュー・ミーティングも行いました。私はこうしたやり取りの中で常に、変わり種だという印象を受けるパターンがありました。それは、Active Record パターンです。このパターンが変わっていると感じた理由は、Martin は Microsoft .NET プログラミング・コミュニティーでは一般的なパターンであると断言していましたが、私は一度も目にしたことがなかったためです。けれどもそれよりも印象深かった点として、このパターンを使用するのが最良の使用ケースは、オブジェクトがフラットな場合であるということです。この印象は、iBatis などのオープンソース・テクノロジーを使用した Active Record パターンの Java 実装をいくつか目にした後、さらに強くなりました。

データベースにマッピングしているオブジェクトが徹底的にフラットな状態 (ネストされたオブジェクトは限定的な例外として、他のオブジェクトとの関係がまったくない) だとしたら、リレーショナル・モデルの機能の利用も限定的だということになるでしょう。実際のところ、顧客満足アンケートや問題チケットなど、紙の書類の電子バージョンにあたるドキュメントを保管している場合は、Cloudant や MongoDB といったドキュメント・データベースを使用するほうが適切です。コードの中から、このタイプのデータベースに対して動作する部分を切り離してサービスにすれば、はるかにシンプルなコードになり、保守するのが簡単になります。

事例 3: リファレンス・データ

オブジェクト・リレーショナル・マッピング・システムで私がよく目にした一般的なパターンには、「テーブル内のリファレンス・データをインメモリー・キャッシュに読み込む」という、テーブルとインメモリー・キャッシュを組み合わせてパターンもあります。リファレンス・データは、頻繁に (あるいは決して) 更新されることはない一方、常に読み取りが行われるデータからなります。その好例は、米国またはカナダの州のリストです。また、医療コードや標準部品のリストという例もあります。このようなタイプのデータは、GUI 内のドロップダウンに取り込まれることがよくあります。ドロップダウンの場合の共通パターンでは、まず、データが必要になるたびにテーブル (通常はフラットな列が 2 つまたは 3 つ含まれるテーブル) からリストを読み取ります。ただし、このパターンではパフォーマンス上の制約が厳しいため、システムでは代わりの方法として、起動時にテーブル内のデータを Ehcache などのインメモリー・キャッシュに読み込みます。

リファレンス・データの問題を抱えているときは例外なく、よりシンプルで高速なキャッシング・メカニズムへのリファクタリングを開始する必要があります。この場合も、Memcached、IBM Cloud 上の Data Cache サービス、または Redis が理想的な手段となります。リファレンス・データがデータベース構造の残りの部分と独立しているとしたら (通常はそうなっているはずですが、そうなっていないとしても、少なくも疎結合されているはずです)、データとそのサービスをシステムの残りの部分から切り離すことが役立ちます。

事例 4: 最悪のクエリー

これまで取り組んだことのある顧客システムのうちの 1 つで、私たちは複合金融モデルの構築に取り組みました。このモデルには、プログラムの操作対象のオブジェクトを作成するためだけに、(6 通り、または 7 通りもの結合がある) 非常に複雑化したクエリーが必要となります。更新となると、複雑さはさらに増してきます。更新処理によって変更された要素を突き止めて、データベースの内容が更新前に作成して操作した構造と引き続き一致するかどうかを調べるだけのために、複数レベルのオプティミスティック・ロッキング・チェックを組み合わせなければなりませんでした。

今思い返すと、私たちが行っていた処理は、グラフとしてモデル化したほうが自然でした。私たちは、それぞれ異なる種類の株式と借入債務で構成され、それぞれ異なる通貨で異なる時期に異なる価格で売られ、それぞれの評価に関する異なるルールで構成された取引のモデルを作成していました。このような状況は、目的とする処理を簡単に行えるデータ構造が欲しいと言っているのと同じことです。グラフであれば、端から端まで行き来してグラフの特定の部分を自由に移動できます。

この場合に適切な手法となるのが、Neo4J または (IBM Cloud 上の IBM Graph データベース・サービスの背後にある) Apache Tinkerpop のようなソリューションです。ソリューションを直接グラフとしてモデル化することで、Java と SQL の複雑なコードの大部分が不要になると同時に、ランタイム・パフォーマンスが大幅に向上する可能性があります。

事例 5: データ・モデルが機能している場合

これまで、リレーショナル・モデルとはデータが「食い違う」4 つの事例を見てきました。次は、メインのエンタープライズ・データ・ストアからデータを切り離そうとすべてきではない事例を紹介したいと思います。

私は顧客のうちの 1 人として、政府機関に協力したことがあります。政府機関は有権者である市民に仕えるために存在しているわけですが、この顧客のエンタープライズ・システム内では市民が何百通りもの形で表現されています。そのため、「この質問をしたこの個人は、このフォームに記入した個人と同一人物なのか」といった単純な質問の答えを見つけることさえ不可能でした。この状態は顧客にとって歯がゆいだけでなく、市民にとっても、間に立たされる IT スタッフにとってもフラストレーションが溜まる状況です。顧客は状況を変えるための取り組みが必要なことを十分承知していました。

顧客にマイクロサービスの話を持ち掛けると、顧客のほとんどは決まって「それは不可能なことだ。すでにエンタープライズ・データ・モデルを構築するためにかなりの投資をしていたのだから」と返してきます。ある意味、それはもっともなことです。エンタープライズ・データ・モデルに深入りして、他の概念と深く結び付いている要素を引きずり出してしまうのは、無駄骨です。データ・モデルが機能していて、問題を起こしていないのであれば、そのモデルを変える理由はまったくありません。

マスター・データ管理への流れ

すべてのデータ・モデルが等しく問題のないモデルというわけではありません。けれども実際のところ、同じような方向へと向かっている別の流れがあります。さまざまなところで同時に発生しているこの流れは、開発者が推進しているのではなく、データ・モデラーと DAB が推進している、マスター・データ管理、つまり MDM への流れです。この流れはある意味で、エンタープライズにおける重要な概念 (たとえば、顧客) に対して複数の見方をするのは誤りであるという考えと同じことです。MDM ツールは、特定の概念のさまざまな見方のすべてを結合し、不要な重複を排除します。

MDM ソリューションは API 中心ではなく、データ中心であるという点は異なりますが、MDM ソリューションを適用すると、一般な結果として、MDM ツールを介した共通の概念へのアクセスを表す一連の API が中央に作成されます。これらの API をマイクロサービス・ベースの手法の基盤として扱ってはならない理由はありません。同じツールで行われた実装ではないことを把握しているだけで十分です。結局のところ、大事なのは API であり、実装ではないということが、マイクロサービス・アーキテクチャーからわかった点となります。

まとめ

この記事では、特定の「コードの雰囲気」から、データ・モデルに問題があるという確信に至り、その問題をマイクロサービスに向けたコードのリファクタリングによって解決する 4 つの事例を取り上げました。このような特定のコーディング問題を 1 つでも抱えている場合は、既存のエンタープライズ・データ・ストアをやめて、別のタイプのデータ・ストアを使用するよう再考するのが得策です。

このシリーズの最終回となる次回の記事では、第 1 回とこの第 2 回で説明した内容を基に、既存のモノリシックなアプリケーションをマイクロサービスに進化させるための手順をステップ・バイ・ステップで説明します。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Java technology
ArticleID=1064766
ArticleTitle=マイクロサービスへのリファクタリング, 第 2 回: データを移行する際の考慮事項
publish-date=02282019