Elasticsearchによるマイクロサービス間検索の基盤をNetflixの事例を参考に構築した話

はじめに

レバレジーズシステム本部 NALYSYSグループ テックリードの桐生です。

NALYSYSとは、ピープルマネジメントを支援する「NALYSYSモチベーション管理」や労務業務を効率化する「NALYSYS労務管理」などの機能を多数持った、人事労務に関わる課題を解決するためのSaaSです。

そんなNALYSYSでは、今年4月に新たに「NALYSYS従業員ライブラリ」をリリースいたしました。こちらのプロダクトではマイクロサービスを跨いだ検索を実現する必要があったのですが、これにより今までにない設計上やパフォーマンス面の問題に直面し、また短い納期の中でこの問題を解決する必要がありました。今回の記事では、これらの問題をNetflixの事例を参考に爆速で解決に導いた取り組みをご紹介いたします。

NALYSYS 従業員ライブラリについて

現在のNALYSYSは、「NALYSYS Admin」に登録された従業員の基本情報を中心として、それにぶら下がる形で「NALYSYSモチベーション管理」や「NALYSYS労務管理」などに追加の情報を保持しています。同じ従業員の情報であっても分野ごとに異なるプロダクトに保存されているため、これらのデータを活用するには複数のプロダクトを行き来する必要があり、ユーザーにとって不便な状態となっていました。

これを解決するために企画されたサービスがNALYSYS従業員ライブラリです。

従業員ライブラリが新たにNALYSYSに加わることで、複数のプロダクトに分散している情報を集約して閲覧することができ、プロダクトをまたいだ従業員の検索も行うことができるようになります。

全プロダクトのデータを集約するという性質上、権限やパフォーマンスに関して今までにない課題に直面することとなりました。また、今回は企画立案〜リリースまでが3ヶ月という短いスケジュールだったため、その期間で実現可能な方法を選ぶ必要がありました。 本記事では、直面したさまざまな課題の中から「プロダクト横断検索」に関わる部分をピックアップしてお届けします。

マイクロサービス間検索における課題

NALYSYSのバックエンドではマイクロサービスアーキテクチャを採用しており、それぞれのマイクロサービスごとに独立したデータベースを持っています。(マイクロサービスアーキテクチャでは各サービスの独立デプロイ可能性を確保するためにデータベースを分離する必要があります)このため、マイクロサービスを跨いだ検索を行おうとすると、検索に利用したいデータが複数のデータベースに分散しているという点が問題となります。具体的には、愚直に検索を実装する場合、複数のマイクロサービスに対してそれぞれデータ取得操作を行なった後、それらを集約して検索結果を構築する必要があります。特に、特定のマイクロサービスに関する検索条件がゆるい場合には大量のデータをロード・転送しなければならないため、データ量に対してスケールしにくくなってしまいます。実際に既存のプロダクトでも在籍状況+プロダクト固有の情報で検索する場合などに同様の問題に直面し、パフォーマンスが低下していました。

今回は、この問題を根本的に解決するため、単一の検索用データベースに全てのサービスのデータを集約することとしました。具体的には、以下のNetflixの事例を参考に、マイクロサービス間に分散したデータをElasticsearchに集約してインデックス化し、横断的な検索を実現します。

netflixtechblog.com

検索システムの構成

構築した検索システムの概要を以下に示します。

先ほど紹介したNetflixの事例と同様、Elasticsearchの検索インデックスに各サービスからかき集めた従業員の情報を合成して登録していきます。実際にユーザーが検索リクエストを送った際には、従業員ライブラリのマイクロサービスがそれをElasticsearch用の検索クエリに変換して検索を実行します。検索処理は全てElasticsearch内で完結し、DBのスキャンが必要ないため高速な検索処理を実現することができました。

インデックスの更新方法について

Elasticsearchに登録されている従業員データは元々のサービスからコピーされたものであるため、元のデータが更新された場合これを随時インデックスに反映していく必要があります。

先ほどのNetflixの事例では、各マイクロサービスが送出するデータ更新イベントをトリガーにしてElasticsearchへのデータ再登録を行うという手法をとっていました。Netflixのシステムでは元々Kafkaに変更イベントを送出する仕組みが整っていたため、このような手法を少ない労力で実装できたようです。

一方、NALYSYSにはNetflixで行われているような変更イベントを流す仕組みがありませんでした。マイクロサービス間を疎結合にするという観点で、Netflixと同様にメッセージベースのやり取りを実装するのが望ましくはあったのですが、開発期間が短い中でそのような仕組みを設計・構築する余裕がなかったため、今回は代わりにLogstashのJDBC Input Pluginを活用した変更検知を実装しています。

JDBC Input Pluginを用いると、データベースに対して定期的にクエリを発行し、データの差分を取り込むことができます。以下の公式ブログに詳しい実装方法が説明されています。

www.elastic.co

この方法を用いる場合、Logstashのデプロイおよび必要な設定ファイルの作成を行うだけでインデックスの自動更新を実装することができるため、自前で更新のための仕組み(差分イベント送出・検知)を実装するのに比べて大きく工数を削減することができます。一方で、各サービスのデータベースの構造とLogstashの設定ファイルが密結合になるためメンテナンス性が低下するという問題も抱えています。今回は短納期を実現するために必要な負債としてこれを受け入れることとしました。

まとめ

ここまで述べた取り組みによって、高速な横断検索機能を予定期間内に作り上げることができました。今回は従業員ライブラリに特化した仕組みとなってしまったので、今後は他のプロダクトにもこの仕組みを展開しつつ、メッセージベースの変更検知によってサービス間の結合度を下げる取り組みも行っていきたいと考えています。

レバレジーズでは、ソフトウェアの力で人事労務に関わる課題解決に挑戦する仲間を募集しています!ご興味のある方はぜひ採用サイトをご覧ください!