CodeZine(コードジン)

特集ページ一覧

サービスの成長や依存による「分断されたモノリス」状態を解体するには? アプリケーション開発の観点から取り組みを紹介

スケーラブルなマネーフォワードの開発組織を目指す、若手プロジェクトリーダーの挑戦 第2回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2021/07/05 11:00

目次

共有リソースの引き起こす問題にどう向き合ってきたか

 こうした問題を受け、共有リソースであるデータベースとライブラリを解体し、モノリシックなサービス群を適切な粒度に分割していく活動が始まりました。データベースの解体という観点では、有志で定期的に改善活動を進めていきました。

 データベースリソースに直接作用する対応として、JOIN操作や他のテーブルと同一トランザクションによる更新操作の必要性の低いテーブルのうち、データ量の多いものを別のサーバーへ移しました。さらに、1時間おきにスロークエリを通知する仕組みの整備、クエリに対してアプリケーションのコンテキストを付与する対応を行うことで、将来の異変に対して対応が取りやすい状態を作るための下準備も行いました。

 しかし、根本的にはそもそも複数のサービスが単一のデータベースへの依存を持っていて全体が密に結合していることが問題であり、それを解消しない限りはどんな対応も問題を先延ばしにしているだけなのは明白でした。特に、難解なライブラリの存在がデータベースによる結合の解消を阻んでいる側面はあり、加えて、どうしても全員本業の傍らで対応するような形式だと力を出し切りづらいといった構造的問題もありました。そこで、特にライブラリの観点からサービス同士の密な結合を解消することを主目的とした、チームを組成することにしました。

 最終的に目指すべき世界としては、「全てのデータはそれぞれ単一のサービスからのみ直接的に参照・更新され」「他のサービスがそのデータを参照・更新したい場合はアプリケーション層で定義されたインターフェースにのっとって操作する」という状態でした。

 つまり、全てのサービスが共有データベースへのアクセスをやめて自身の専用データベースを持ち、他のサービスとは通信(API)によって協調する状態のことです。この状態を目指すことで、ライブラリのうちデータにひもづくロジックは全てどれかのサービスに持ち帰ることができるだろうと考えています(※注1)。

※注1

 なお、この記事の主題から離れるため簡単にだけ触れますが、ライブラリにはAPIクライアント実装のような「データに直接ひもづかないがサービス間で共通で持っておきたいロジック」もありました。こうしたロジックまで無理に解体してそれぞれのサービスに持ち帰る必要はなく、データに直接ひもづかずインターフェースのみを定義してくれているのであればライブラリとして有用なので残しておこうと考えていました。

図2:マネーフォワードのサービス群の現状と目指したい世界
図2:マネーフォワードのサービス群の現状と目指したい世界

 ここではまず、ライブラリを通して操作しているデータをテーブル単位で列挙し、それぞれどのサービスから参照・更新があるのかを調査していきました。「テーブルAのデータはサービス1から参照、サービス2から参照・更新されている」「テーブルBのデータは全てのサービスから参照・更新されている」……といった情報を表形式で整理していきました。

 その上で、データを最終的にどのサービスで管理するべきかを整理していきました。実際には、テーブルの単位できれいに整理していけるデータばかりではなく、レコード単位やカラム単位での整理が必要なデータも存在し、これらに関しては細分化して整理しました。

 同時に、現行のデータ構造や仕様が本当に今やりたいことと合致しているのかをビジネスサイドのメンバーも含めて議論しました。ライブラリの解体に際して、全てのニーズに応えると対応にかかる工数が肥大化する恐れがあり、時間をかけて改修を行っても終わった頃には外部環境の変化によって、別の状態が最善になってしまっている可能性もあります。そのため、必要ないものをコストをかけて改修することや、すぐ対応できる追加改善を無視して改修することは損失であると判断しつつ、なるべく少ない工数と短い期間でどうすれば費用対効果を高く盛り込めるかを検討しました。

 これはデータを整理する前の段階で既に判明していたことですが、例えばユーザーそのものを表現するデータなどは既存のどのサービスにも属するものではなく、専用のサービスで管理されるべきだという議論もありました。ユーザーのデータはわかりやすい例ですが、それ以外にも個別にサービスに持ち帰るべきか、専用のサービスを開発すべきかを今後のビジネス的な展望も想定しつつ判断すべきでした。議論し、専用サービスを作るべきとなったケースでは、専任のチームを組成しサービス開発を行うことにしました。こうした専用サービスのことを社内では、基盤サービスと呼称することもあります。基盤サービスの開発に関しては次回の記事で説明する予定です。

 こうした整理の結果、ライブラリで管理している全てのデータはどれかのサービスに持ち帰る、もしくは基盤サービスを作りそこで管理するという方針で進めそうだと判明しました。2021年6月の時点で、まだ計画した全てが完了しているわけではないですが、最後にライブラリの解体を進める上で行った取り組みについていくつか紹介します。

ライブラリの解体に向けて行ったこと

 テクニカルな部分として、データのライフサイクルを意識した更新系の操作の整理というのがありました。前のセクションでも述べた通り、テーブル単位、カラム単位、レコード単位の3つの分割軸でデータへの参照・更新を整理しました。それでも今のままの実装では、特定のサービスへ持ち帰ることの難しいデータも存在しました。参照までのどこかのタイミングでデータの作成・更新を行えていればよいため、作成・更新のタイミングをずらす変更を検討しました。

 「共有ライブラリが引き起こす問題」で述べた「あるサービスを始める際には必ず存在していてほしいデータをこのライブラリ上で作成するようなロジック」がこれに当たります。事前の整理の時点では、データごとにどのサービスから参照・更新が行われるのかに着目しましたが、データのライフサイクルがサービス上のどのイベントとひもづいているのかを意識した整理も有用であると考えています。

 開発時に開発者たちが方針・規約として参照できるドキュメントを整備することも行いました。ライブラリで従来提供していたどのサービスでも備えてほしい機能の実装は、サービスごとに行ってもらいました。実装の詳細までライブラリとして提供することの難しさは今まで書いてきた通りですし、将来も全てのサービスが同じ言語やフレームワークを用いるという仮定を置くのは難しいと判断したためです。

 実装自体の提供は行わない一方で、サービスの開発チームが個別にゼロから設計や仕様を検討し実装していくのは手間がかかりすぎると考えたため、仕様や設計に関して推奨となる方針・規約をサービス横断的に打ち出して開発時の参考にしてもらうことにしました。開発チームがサービスのコア機能以外の実装に関して、なるべく悩まずにスピード感を持って進められ、また、個別のサービスの要件で推奨となる方針・規約を逸脱したい場合は、意識的に逸脱できる仕組みだと理想的なのではと現時点では考え、こういったことを実践しています。

まとめ

 共有のリソースであるデータベースとライブラリを核とした、モノリシックなアーキテクチャがマネーフォワードの初期の開発をどう支えてきたか、マネーフォワードのサービス群が成長するにつれてそれらがどう問題を引き起こすようになってきたのか、その問題に対して我々がどう対処しているのかについてご紹介してきました。

 とはいえ、部分的には問題を解消しつつも、まだこの問題を完全に解決できているわけではありません。やるべきことは残っている状態です。さらには残っているタスクを地道に進めていけば完遂できるという認識で進めているわけではなく、外部環境やそれによるサービス要件や開発の優先度に合わせて柔軟に進めていく必要があるのだろうと考えています。それでもここまでの知見は組織の拡大に合わせて起きうる問題の一例としてなんらかの参考になればうれしいです。

 次回は、サービス群の密な結合を解消していく上で中心的な存在となり、それと並行して新しいサービスを密な結合を意識せずに開発していく上で重要な存在となる基盤サービスについて、その存在の重要性と開発時の取り組みをご紹介します。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:スケーラブルなマネーフォワードの開発組織を目指す、若手プロジェクトリーダーの挑戦

著者プロフィール

  • 古濱 有佑(フルハマ ユウスケ)

     クラビス新規事業開発部 部長。  2016年にインターン、2018年4月に新卒エンジニアとしてマネーフォワード入社。  マネーフォワードのビジネスカンパニーにて2020年3月からプロダクト横断的な課題の解決を目的とした『わり算グループ』を組成しリーダーを担当。2021年6月よりグループ会社であ...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5