弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

Apache Solr から OpenSearch に載せ替えた話

検索しているユーザー(イメージ)

はじめまして。弁護士ドットコム事業本部でエンジニアをしている狩野です。

弁護士ドットコムのサービスにはいくつかの検索機能があります。主に「みんなの法律相談」「弁護士検索」「弁護士ドットコムニュース」などで使われています。 これらは Apache Solr(以下、Solr)という検索システムで動いていました。 これを OpenSearch という別の検索システムに載せ替えました。

経緯

弁護士ドットコムのサービスにはいくつかの検索機能があり、そこで Solr を使っていました。 確認できた限りでは 2013 年から 10 年近くの間、使っていたようです。もっと以前から使っていた可能性もあります。 だいぶ昔の話なので Solr が導入された経緯などは不明ですが、当時の判断としては Solr を選んだのは妥当だったと考えています。

しかしながら、長年の運用もあって定期的に障害が発生していました。 障害時の状況としては、アクセスの集中からメモリリークのような挙動になって暴走して障害となる感じでした。 障害の頻度は半年に 1 回程度でした。

Solr の名誉のために付け加えておきますと、Solr 自体の問題ではなく我々の使い方に問題があったと考えています。

弁護士ドットコムの Solr は単一障害点になっていました。 Solr がダウンすると各機能が軒並みアクセスできなくなりました。

設定については多数の機能を使っていることや過度なチューニングが行われているため、変更がほぼ不可能な状態になっていました。 障害の対応やパッチ適用の調査など、運用の負荷も大きくなっていました。 「いつ障害が起きるかわからない」という心理的な負担も大きかったです。

こういった状況から、Solr を止めることを検討しました。 その結果、安定稼働と運用負荷の軽減を目指して新検索基盤を用意することになりました。

載せ替え前のシステム構成は以下のとおりです。 要素は少ないのですが、モノリスの PHP コードと Solr だけですべての用途を担っていました。 検索の仕様が PHP コードと Solr に依存していて複雑になり誰も手が出せない状態でした。 インデックスについては操作が不可能でした。

載せ替え前のシステム構成図

選定

最初の時点では、新しい検索システムには社内での利用実績があった Elasticsearch を考えていました。

現在では Elasticsearch は検索システムのスタンダードのひとつです。2022 年 11 月現在、DB-Engines Ranking of Search Engines で 1 位となっています。 検索システムには安定稼働が求められるので、稼働実績の少ない最新のシステムよりも、実績の多いシステムを選択すべきだと考えました。

検索システムを選定している間に、ライセンスの問題などの理由から OpenSearch が誕生しました。

弁護士ドットコムのインフラは AWS で動いています。Solr も Amazon EC2(以下、EC2)上で動いていました。 AWS には Amazon OpenSearch Service という OpenSearch を扱うマネージドサービスがあります。これにより EC2 を脱却し、検索システムの運用は AWS に任せることができると考えました。 OpenSearch の利用実績はなかったのですが Elasticsearch のフォークなので問題ないと考えました。

このような経緯があって、最終的に OpenSearch を選びました。

Amazon OpenSearch Service の利用では互換モードを有効にする設定にしています。これにより利用開始時は基本的に Elasticsearch と変わりなく利用できました。

機能

Solr 時の反省を踏まえて、シンプルな状態を維持できるように利用する機能はできるだけ絞りました。利用している主な機能は以下のとおりです。

Index APIs でインデックスの作成や更新をします。

Document APIs でドキュメントの一括操作を行います。Document APIs の中では Bulk のみを使用しています。Bulk を使って文書の追加、更新、削除をすべて行っています。各行の区切りに \n を使用する ndjson というフォーマットでリクエストします。

Search でドキュメントの検索をします。検索結果をそのまま使うわけではなく、検索結果のドキュメントの ID(識別子)からデータベースのオブジェクトを取得し直しています。コストだけなら OpenSearch から取得したドキュメントをオブジェクトとしてそのまま使うほうがよいです。ですがここでは Solr 利用時の経験から、多少コストは掛かっても最新のデータベースのオブジェクトを使用したほうが検索システムを使っていないコードとの差がなく明確で利用しやすいと考えました。

Term vectors は用語ベクトルです。Solr にも同様の機能があって弁護士ドットコムではレコメンド機能の一部として使われていました。検索システムの機能としては少し性質が異なるので別のシステムに移すことも検討しましたが、OpenSearch でも実現できることがわかったので残すことにしました。

利用を限定することで OpenSearch に依存し過ぎず、いざとなればさらに他の検索システムへの載せ替えも可能だと考えました。

モジュール

現在の弁護士ドットコムでは、適切な機能単位でモジュールに分割して実装しています。 先述の機能を使用するために以下のモジュールを作成しました。

  • apiInternal
  • searchIndexer
  • searcher

apiInternal は内部 API です。外部アクセスを遮断しています。先述の Bulk に対応した ndjson フォーマットのレスポンスを返します。

searchIndexer は定義した内容に従ってインデックスや設定の登録、更新をします。設定ファイルは PHP の配列で定義していますので、コードにコミットできるメンバーなら誰でも操作可能です。

searcher はドキュメントを取得します。一般のユーザーが検索したときに利用されるモジュールです。

AWS サービス

Amazon OpenSearch Service 以外に、以下のサービスを利用しています。

  • Amazon SQS(以下、SQS)
  • AWS Lambda(以下、Lambda)

Solr 時はデータベースの登録、更新とあわせて同期的に更新していたのですが、たまに通信エラーが発生していました。この反省を踏まえて新検索基盤では非同期処理に変更しました。さらに AWS のサービスにすることでコードのスリム化と信頼性の向上になりました。

利用する機能はできるだけ絞りました。利用している主な機能は以下のとおりです。

SQS はドキュメントの差分更新キューとして利用しています。データベースの登録、更新をフックにオブジェクトの ID がメッセージとして SQS に送信されています。

SQS にはデッドレターキューがあります。メッセージがデッドレターキューに移動されると Datadog から異常が通知されて検知できる仕組みにしています。

他にもいくつかの項目を Datadog で監視しています。

Lambda はドキュメントを操作します。SQS からメッセージ、(つまり、オブジェクトの ID)を取得して、メッセージを利用して先述の apiInternal から取得した情報をドキュメントとして一括操作します。

可能な限り運用を AWS に任せたかったのですが Lambda のコードは書かないといけませんでした。 Logstash など検討しましたが、現状のデータの仕様で対象データが更新日を持っていない場合があり、更新対象のデータを正しく選択できない可能性があるため、諦めました。

ちなみに、ローカルの開発環境は LocalStack を使っています。少し癖がありますが大きな問題はなく使えています。

最終的に、載せ替え後のシステム構成は以下のようになりました。 載せ替え前と比較して要素が多くなってはいますが、それぞれの用途はシンプルで明確になりました。

載せ替え後のシステム構成図

実装

弁護士ドットコムは PHP で書かれているので、クライアントに最初は Elasticsearch の PHP client を使っていました。現在は OpenSearch になって OpenSearch の PHP Client を使っています。

Solr が単一障害点になっていた過去の反省を踏まえて、実装を非同期処理に修正しました。これにより OpenSearch が止まってもサイトは閲覧できるようになりました。

クライアントの利用箇所を先述したモジュールの searchIndexer と searcher に限定しているので、いざとなればクライアントの変更もそれほど難しくはないと考えています。

リリース

まずは「みんなの法律相談」から対応しました。2022 年 11 月現在の相談件数は約 120 万件ほどになりますが問題なく検索できています。

検索以外にも関連度判定などありましたが、その辺りは先述の Term vectors などを利用して修正しました。それなりに難解な箇所もありましたが、ひとつずつ直しました。

結果、Solr 時と比較して圧倒的に安定稼働しています。

その後、別の担当者によって「弁護士ドットコムニュース」が対応されました。レビューなどで少しコメントをしたものの、基本的には担当者のみで実装を進めていただき、大きな問題もなくリリースされました。汎用的な新検索基盤になったことを証明しています。

さいごに

弁護士ドットコムにおける Solr から OpenSearch への載せ替えについてお話させていただきました。

それなりに要素が多くなりましたが、それぞれの用途は明確で全体像がはっきりしました。 これだけ把握していればコードリーディングは難しくなく今後の改修などにも耐えられると思っています。

また OpenSearch から別の検索システムに変わる日が来るまで、その日までは安定稼働してくれる新たな検索基盤を用意できたと考えています。

弁護士ドットコムでの検索システムの理解や、同じように検索での安定稼働を目指している人たちの一助になれれば幸いです。