見出し画像

最小構成でSolrを運用する

こんにちは、ネコ派メタラーです。ナビタイムジャパンでスポットデータ運用基盤の開発を担当しています。

この記事では、コスト最優先で全文検索システム Solr を運用する工夫についてお話しします。業務システムという限られた条件での事例ではありますが、スタートアップビジネスなど他の用途においても参考になるかもしれません。


コスト最優先の全文検索

スポットデータ運用において、1,000 万件を超えるスポットデータから調査対象を見つけ出すため、フリーワードでの検索が必要になる場面は多々あります。そのため、スポットデータ管理システムには全文検索システムが導入されています。現在は Apache Solr を使用しています。

全文検索システムはインフラコストが大きくなりがちですが、スポットデータ管理システムの Solr はサーバー 1 台 (CPU 2 core、メモリ 8 GB、ストレージ 50 GB)だけで稼働することでコストを抑えています。限られたメンバーだけが使うため同時利用者が少ないこと、多少ダウンタイムが発生しても利用者と管理者がすぐにコミュニケーションをとれることが理由です。

求められる品質

コストを優先しているとはいえ、品質について求められることはもちろんあります。

  • 長時間ダウンすると業務が停止するため、そこそこの可用性が必要

  • 検索性能が業務効率に直結するため、継続的な開発・デプロイが必要

  • データ整合性が重視されるため、更新頻度が高いことが望ましい

当社には製品向けスポット検索を担当するチームはありますが、スポットデータ運用チームにおいて全文検索は副次的興味であり、全文検索エンジニアが在籍する機会は多くありませんでした。検索機能改善はあまり行われておらず、更新頻度も夜間に 1 回全件更新が実行されるのみでした。

全文検索システムの運用経験者である筆者がスポットデータ運用チームに参加したこともあり、最近はこの検索システムの機能改善に取り組む機会が増えてきました。よりよい検索体験を提供することはもちろん、チームの開発体験を改善することも含みに、システムに工夫を施すことにしました。

解決策

機能改善を進めるにあたり、「1 日に 1 度しかデプロイできない」という点が最大の障壁に感じました。クエリ解析の変更はいつでもできますが、抜本的な改善となるとインデックス解析にも手を入れることになります。インデックス解析の変更は全件更新によって反映されますので、1 日 1 回しか変更できない状況は改善するべきだと考えました。

もちろん利用者の目線でも、更新頻度が低い現状は望んだ姿ではありません。まずは全件更新を頻繁に実行することを目標にしました。

全件更新は負荷が高く、時間のかかる処理です。これを日常的に実行するためには、以下の問題を防ぐ必要がありました。

  • 更新中に検索機能が利用できなくなること

  • 更新失敗により検索データに欠陥が生じること

コミット保留

Solr に送信されたデータはコミットするまで検索対象となりません。シンプルな方法ですが、全件インポートが終わって初めてコミットするフローにして、更新中でも更新開始前のデータを検索できるようにしました。

コミット保留は一時的な保証にすぎません。インデックスファイルは変更されており、なんらかの要因で Solr がリロードされると未コミット情報がすぐ反映されます。実際、不意に再起動してしまいインデックスを消失させてしまったこともありました。

コミット保留はあくまでも検索機能を継続する手段としてのみ用い、障害対応は次に紹介する「バックアップ復旧」に頼ります。

バックアップ復旧

Solr にはバックアップとリストアを行う機能があります。更新開始時にバックアップを作成し、更新失敗を検知した場合は直近のバックアップに自動的にリストアするようにしました。

今回はシングルノードですので、最もシンプルな Backup API を用いました。バックアップを明示的に削除する API はなく、毎回残し続けるとストレージも管理する必要が生じますので、"numberToKeep=1" を指定してバックアップをローテーションすることにしました。1 にした理由は単にストレージを節約するためで、履歴管理・耐障害性・ストレージのコストなどの要件次第で調整するところです。

なお、更新失敗を検知できなくても 1 回分のバックアップが残り続けるため、直近の更新で不測の事態が発生した場合は手動で切り戻せるようになりました。

成果と妥協点

これらの工夫のおかげで「いつでも全件更新できる」という状態を作ることができました。現在は 1 日 3 回の自動更新を行い、作業者が実施した変更がその日のうちに検索システムに反映されるようになりました。また、デプロイ頻度をデイリーからオンデマンドに変えることができ、機能改善の敷居が大きく下がりました。

とはいえ、無理をしているところもあります。以下は妥協点です。

  • やはり 1 台しかないので、サーバーダウンによる機能停止は受け入れざるを得ません。メンテナンスによるサーバー停止は利用者に一声かけています。

  • 2 回以上連続で失敗した場合は復旧できません。この場合は利用者とコミュニケーションをとりながら解消していくことになります。実際に問題が表面化した場合、バックアップ件数を増やして緩和しようと思います。

  • 並列更新するとバックアップ復旧先がおかしくなります。現在はほとんど自動更新に任せているため問題になっていませんが、今後制御が必要になるかもしれません。

対応を通しての所感

サーバー 1 台という構成は製品としてはオススメできませんが、自社業務システムなど利用者が限られ、コスト優先で運用する場合には実用的だと思います。製品開発の過程においては、シンプルゆえに扱いやすいので、スタートアップビジネスなど「まずはやってみる」というフェーズでは使えるかもしれません。

ちなみにエンジニア個人としては、可用性を担保するというと冗長化に頼りがちな現代において「サーバー 1 台でどれだけうまく運用できるか」と言うテーマで試行錯誤を繰り返す経験はなかなか貴重だと思いました。基本に立ち返った気持ちで楽しく取り組むことができました。

この記事によって全文検索を用いる選択肢が少しでも増えれば幸いです。