Elasticsearch で高速な検索システムを構築した話「研究発表会vo.01〜ynishi編〜」

Date
May 30, 2023

はじめに

しくみ製作所の西口です。今年度よりしくみ製作所では、社内において研究発表会という知見を共有するイベントを開催することになりました。先日第1回目が終了したのですが、「Elasticsearchで検索システムを構築した話」と題し、私が登壇しましたので、その内容をお伝えできればと思います。

image

研究発表の概要

今回の発表では実際の案件において、Elasticsearch を使い高速な検索システムを構築した話をしました。対象となる案件は、条件付きで CMS を再構築するものです。具体的には、「各種データ(5種類)の検索に関して、レスポンス速度が速くかつ柔軟な条件で検索できること」という条件がありました。

この条件をクリアするために Elasticsearch で検索システムを組むことにしました。メインのデータストアである RDB からデータ自身 + データに紐付けられているS3上の添付ファイルの内容などをできるだけ速く同期させる仕組みを作りました。

結果として、一部問題も残っているものの概ね RDB への更新から10秒ぐらいのラグで、最大500万件ぐらいのデータを数ミリ〜数十ミリ秒で検索できるようになりました。

より具体的な条件

対象となる CMS の刷新にあたって、以下のような柔軟な検索要件がありました。

  • あるデータに紐付けられた添付ファイルの中身の文言にマッチする検索
  • 紐づく孫データのある項目にマッチするデータの祖父データの検索
  • それをレスポンスが悪くなることなく検索できる

私は別のシステムで Elasticsearch を使ったことがあり、Elasticsearch を使えば柔軟かつ検索速度も速いという経験があったため使ってみることにしました。

システムの構成と同期処理

今回の検索システムは、Elasticsearch と Logstash を使って構築しました。

RDB側のテーブルの単位でいうと5テーブルに関してそれらに紐づく親、一部の子テーブルのデータ含めて1テーブル最大500万件ぐらいのデータを Elasticsearch に同期し検索できるようにしました。

RDB と Elasticsearch の同期処理については、Logstash で同期しており、SQL で Easticsearch 側のindex に対応する json を組み立ててそれをそのまま upsert する方式にしました。

添付ファイルについては、ファイルのアップロードと同じタイミングで中身抽出するのが少し難しかったため、別途中身抽出バッチをつくり非同期で添付ファイルの中身を保持するだけのテーブルに更新していき、そのデータの更新をトリガーに Logstash に拾われるようにして同期しました。

一部データ量が多いレコードに関して同期が詰まる問題が合ったりするものの、ほとんどのケースでRDB更新後数十秒程度までには同期され、検索時間も数ミリ〜数十ミリ秒程度で検索できるようになりました。

良かった点

Logstash 方式により同期に多少のラグが発生することとなりましたが、この仕組だけで初期移行、トラブル時の再移行などもまかなえて結果的にはお得に運用できている気がします。

このシステムとは別のシステムで、S3 に置かれた json ファイル -> Elasticsearch の同期に、S3 のファイル作成、削除イベントをトリガーに Lambda を起動し、Elasticsearch への連携処理を実装してみてもいますが、やはりこちらのほうが(正常に実行された場合は)ほぼリアルタイムに連携されるためその点では Logstash よりも優れていそうでした。

悪かった点

ちょうど AWS と Elastic 社の OSS ただのり問題の最中に使用するバージョンを決定することになりました。

結果的にはそれほど新機能は必要でなかったため、その時点での AWS の Elasticsearch (現Opensearch)サービスの最新だった7.9.3で実装しています。結果的には特に問題発生していませんが、その後の Elasticsearch に実装された新機能などが使えないのが少しもったいないと感じています。(例:Elasticsearch の7.11で入ったが Opensearch (= Elasticsearch 7.10互換)ではまだ未実装のランタイムフィールド機能など)

また、何度か出てきていますが、Elasticsearch でのデータの保持の仕方上、RDB でいう、親、子、孫という3階層になっているデータの親データが変更されると、それに紐づく全部の子、孫も自動的に再連携されてしまい、例えば孫データの件数が大量(数十万件ぐらい)だとバッチが詰まることが発生しています。これはまだ完全には解消されてはいません。

さいごに

研究発表会を開催するにあたり、事前にアンケートを実施し社内にて興味のあるテーマを絞り込んでいたこともあってか、業務時間内での開催でしたが、たくさんの方に参加していただきました。ありがとうございました。今回の資料を下記に置いておきますので、ご興味のある方はまたご覧になってください。

研究発表会は第2回、3回と続いていく予定ですので、次回もよろしくお願いします。こうして発表したことが、皆に活用され、実際の開発を手助けするものとなれば嬉しいです。

Elasticsearchで検索システムを作った話(公開用).pdf622.7KB

🖋
新着記事