SQLからGo + gRPCに移行。ミイダスのユーザー検索を高速化対応
こんにちは。ミイダスTech Officeです。ミイダスにおけるユーザー検索の高速化を図るため、SQLからGo + gRPCへの移行を実施し、技術的な課題を解決しながら開発を進めてきました。
今回のインタビューでは、そのプロジェクトを担当した宮本さんと中田さんに詳細について話を聞きました。
ユーザー検索の高速化を目指すプロジェクト
プロジェクトメンバーの役割分担
宮本:私の主な役割は全体のアーキテクチャ設計と、それに基づいたテクニカルリードでした。具体的には、システム全体の設計方針を立案し、それがうまく動作するか検証するためのプロトタイプの開発やテストの実施、そしてシステムのパフォーマンスを測定するベンチマークテストの設計と実施を担当しました。私が設計したアーキテクチャに基づいて、具体的なコードの実装は中田さんや他のチームメンバーが担当しました。
問題が生じた際のトラブルシューティングを行うなど、開発の現場と一緒にプロジェクトを推進していきました。
実際の開発の期間や参加人数
中田:私がこのプロジェクトに参加したのは、前年の4月でした。その時点から約半年の期間をかけて、ユーザー検索の高速化を目指すプロジェクトを進行させました。私たちバックエンドチームは5名で、それぞれが特定の役割を持ちながら協力して作業を進めました。具体的には、マッチング処理自体を開発するメンバーと、そのマッチング処理を他のサービスと統合させる役割を担当するメンバーに分かれて作業を進めました。私自身は、新しいマッチング処理をサービスに統合するタスクを主に担当しました。
ミイダスの複雑なユーザー検索条件の課題と取り組み
Go言語とgRPCを採用した背景
宮本:私がミイダスで働き始めてから6年間、ユーザー検索の速度問題は一貫して存在していました。これはユーザーが増えるにつれて、一層顕著になりました。通常、ユーザー検索はSQLやElasticsearchを用いて実行されます。私たちのサービスも初めはSQLを採用していました。しかし、検索条件が複雑化し、ユーザー数が増加すると、それに伴い検索速度も遅くなるという問題が浮上しました。
ミイダスのユーザー検索は、プロフィール情報が多岐にわたり、検索条件も非常に複雑であるという特性があります。私たちはElasticsearchという選択肢も検討しましたが、これらの複雑なユーザー検索要件をSQLやElasticsearchで満たすことは難しい課題でした。そこで私たちは、Go言語で全体のシステムを書き直し、元となる情報をメモリ上に配置するという新たなアプローチを採ることにしました。
私たちがGo言語とgRPCを採用した背景には、スケールアウトの観点がありました。一つのサーバーだけに情報を保持していると、やがてそのサーバーの限界に達し、スケールアウトする必要が出てくると考えました。現在私たちはAWSのRDBサーバを利用し、レプリケーションを活用していますが、gRPCを用いたサーバー形式でも同様にスケールアウトできるようにすることが求められました。そのため、私たちはgRPCのサーバーを複数起動し、APIサーバーからユーザー検索リクエストを受け取り、検索結果を返す形式を採用しました。これにより、ユーザー数の増加に対応しながら、パフォーマンスの問題も解決することができました。
Go言語は、シンプルでパフォーマンスも優れている一方で、メモリ管理などの面での自由度も高いという特性があります。また、gRPCは高速な通信性能と強力なスケーラビリティを持っています。これらの特性を活かすことで、私たちはユーザー検索のパフォーマンス向上と、ユーザー増加に対するスケーラビリティの確保を両立することができたのです。
私たちの開発プロジェクトは、技術的な課題解決だけでなく、ビジネスの成長にも寄与しています。ユーザー数の増加に対応しつつ、より高速な検索体験を提供することで、ユーザー満足度の向上にもつながっています。
HTTPとgRPCの動作の違いの理解と適応
宮本:当社でgRPCを導入したのは初めてのことだったので、新しい技術に対する学習と理解が必要でした。どのような実装がgRPCサーバーとして適しているのか、その後の拡張性をどのように確保するのか、といった点については特に注意深く考えていました。
開発当初はデータベースやHTTPとは異なる接続管理の扱いに苦労しました。特に、gRPCでは一度接続するとそのまま続いてしまうという性質があったからです。
HTTPでは接続後に自動的に切断されるのに対し、gRPCではクライアントが切断してもサーバー側の接続が残ってしまうため、接続を終了するためには明示的に切断しなければなりません。この点を認識しなかった初期の段階で、クライアントの接続数が急激に増加するという問題に直面しました。これは見かけ上は簡単そうなことですが、HTTPとは動作が異なるため、その違いを理解し適応するのには一定の時間と労力が必要でした。
大規模メモリ管理とパフォーマンス最適化
中田:私が特に難易度を感じたのは、全ての登録ユーザー情報をメモリに載せる必要があったことです。当時、約80万人の登録ユーザーがいたのですが、それら全員の情報をメモリに載せてみると、なんと約20GBのメモリが必要となりました。
この20GBという数字は、不要な変数の参照が残っていたのが原因でしたが、修正した後でも、約10GBのメモリが必要となりました。私自身、これほどのメモリを使用する実装は初めての経験でしたので、メモリ使用量の管理は大きな課題となりました。
宮本:そのメモリ使用量は、AWSのDockerコンテナサービスのコストにも影響します。CPUやメモリの量を増やすほど、コストも増えてしまいます。そのため、メモリ使用量を最小限に抑えつつも、ユーザー検索機能の拡充時にメンテナンスが行える状態を保つために、多くの調整が必要でした。
また、ローカルの開発環境もDockerを使用していたためメモリ制限の問題にぶつかり、 gRPCサーバーに全ユーザー情報をメモリにロードすることができませんでした。他の会社が同じような状況に直面した際にどのように対処したのか、当時は非常に気になっていました。
中田:さらに、メモリの初期ロード時間も大きな課題でした。初期段階では10分以上もかかっていたのですが。並列処理などの対応がなされ、最終的には1分以内に終わるようになりました。この改善により、開発効率も大幅にアップしました。
宮本:テストの際には、データベースから直接ロードする必要がないので、一旦ファイルに出力してからロードするといった方法を採用しました。これにより、テストの効率化を図ることができました。
これらのような課題を一つ一つクリアしながら、gRPCの導入とユーザー検索機能の高速化に成功しました。これらの経験は、今後の開発にも大いに役立つと考えています。
システムパフォーマンスの向上とユーザー体験の強化
ユーザー検索高速化への挑戦
宮本:今後、ユーザー検索の高速化という課題はさらに深化していくと予想されます。ユーザー数の増加や、より複雑な検索条件の設定など、ユーザーのニーズに対応するためには、私たちは新たな技術を取り入れ、その特性を最大限に活かすことが求められます。
今後は、これらの知見を活かし、システム全体のパフォーマンス向上を目指していきます。
中田:このプロジェクトは、ユーザー検索とマッチング処理の高速化だけでなく、システム全体の可読性やメンテナンス性の向上をもたらしました。これにより、新たな機能追加や改修が必要となった場合でも、迅速かつ効率的に対応できる体制が整いました。また、ユーザー検索の高速化は、ユーザー体験の向上にも寄与しました。
今後もユーザーの利便性を最優先に考え、システムの改善を進めていくつもりです。このプロジェクトで得た知識や経験は、それらの努力を支える貴重な資産となります。
最後に
宮本:私たちのプロジェクトは、新たな技術と既存のシステムを組み合わせて、具体的な課題を解決した一例です。初めての技術採用は困難な場面もありますが、それを乗り越えた時に得られる成果は大きいです。具体的には、今回私たちはGo言語とgRPCを採用することで、システムのパフォーマンス向上だけでなく、コードの可読性やメンテナンス性の向上も実現しました。他のエンジニアの皆さんにも、新たな技術を恐れず、積極的に挑戦することをお勧めします。
中田:一方で、技術の導入だけが全てではありません。私たちのプロジェクトでは、新技術の導入と並行して、システム全体の設計を見直すことで、さらなる効率化を実現しました。個々の問題に対する解決策を探すだけでなく、全体の設計を見直す視点も持つことで、より大きな成果を上げることができます。このような全体視点の持ち方や、複雑な問題へのアプローチが、皆さんのチャレンジに役立つと嬉しいです。
これからもミイダスは、ユーザーにとって最高の体験を提供するために、技術の進化とともに成長し続けます。私たちの取り組みが皆さんの何かの参考になれば幸いです。
ミイダス Techについて
ミイダスでは、様々な技術イベントを開催しています。connpassやYouTubeチャンネルでミイダスグループのメンバーになった方には、最新の開催情報やアーカイブの公開情報が届きますのでぜひご登録をお願いいたします。
イベントページ:https://miidas-tech.connpass.com/
Twitter:https://twitter.com/miidas_tech
この記事が気に入ったらサポートをしてみませんか?