【Elasticsearch】1900万点に及ぶ商品データ作成の時間を約67%短縮できた構成と工夫

初めまして、EC基盤グループ サーチチームの壷井です。 モノタロウでは2019年10月頃より新規検索システムの設計・開発を進め、今年の4月頃にECサイト(monotaro.com) 検索ページの裏側の検索システムを従来のSolrからElasticsearchに100%移行*1しました。この移行は将来の商品点数やリクエスト数の増加を見据えたバックエンドの大規模な改修で、ここまで約2年半ほどプロジェクトを進めてきました。今後もECサイトのすべてのページの完全移行に向け引き続き開発・運用を行っていきます。 今回はこのプロジェクトのなかで私が担当してきたElasticsearchへの日々のデータの洗い替え(日次更新と呼んでいます)ワークフローのシステム構成と工夫などについてお話します。

モノタロウの検索システムの紹介

日次更新のシステム構成

Elasticsearchを用いた検索システムはGoogle Cloud Platform(以下、GCP)上で構築されています。データベースに格納されている商品データを加工し、Elasticsearchにデータを投入、検索可能になるまでの日次更新ワークフローのシステム構成は下図のように実現しています。

処理の流れ

① リアルタイムデータ同期

MySQLのデータをBigQueryにほぼリアルタイムで同期します。
詳しくはこちらの記事を参照ください。 tech-blog.monotaro.com

② 日次商品データ生成

サイト上に表示する商品情報を生成するワークフローを1日2回実行しています。生成したデータを別のBigQueryデータセット・テーブルに保存します。 ワークフローエンジンにはdigdagを使用しています。このワークフローエンジンの選定経緯についてはこちらの記事を参照ください。 tech-blog.monotaro.com

③ Spannerデータ投入

Dataflowを使用し、②日次商品データ生成 で作成した商品情報をBigQueryから取得してCloud Spannerに投入します。Cloud Spannerを商品ID(product_id)をキーとしたKey-Value Store(KVS)として使用しています。

④ Elasticsearchデータ変換

③Spannerデータ投入 と並行して、②日次商品データ生成 で作成した商品情報をDataflowでBQクエリを実行することで検索に使用するための商品データに変換、変換後のデータを圧縮してGoogle Cloud Storage(以下、GCS)に出力します。ここではやや複雑なBQクエリを実行していますが、BigQuery Storage API をDataflow内で使用することで通常よりも変換処理の時間を短縮できています。

⑤ Elasticsearchデータ投入

④Elasticsearchデータ変換 以降にバッチ処理でElasticsearchクラスタへデータを投入しています。それぞれの処理の流れは以下の通りです。

  • ⑤-a. Logstashインスタンスを起動し、GCSに出力した商品データをデータ投入用のElasticsearchクラスタに投入します。投入完了後、データの最適化(Force Merge)を実施します。
  • ⑤-b. データの投入完了後、データ投入用Elasticsearchクラスタのスナップショットを取得します。
  • ⑤-c. 取得したスナップショットを検索用のElasticsearchクラスタへリストアします。

検索用のElasticsearchクラスタは常にAPIからデータ参照されているため、データを直接検索用のクラスタに投入すると、検索パフォーマンスに悪影響があります。そのため、データ投入用のElasticsearchクラスタをデータ投入前に自動構築し、上記の処理完了後に自動削除するようにCloud BuildトリガーやTerraformを使って実現しています。

⑥ エイリアス切り替え

毎日0時に検索用Elasticsearchクラスタで新たに検索に使用するデータにエイリアスを切り替えます。

工夫したところ

モノタロウの商品データは販売中の物だけでも現在およそ1900万点存在し、かつ、その1つ1つの商品に関する情報(属性)が多いため、毎日のデータ更新は膨大な処理時間を必要とします。これまでのSolrでもここのデータの変換・投入処理は多大な時間を要しており、下図のように16時に変換・投入処理を開始してから投入完了するのは22時30分頃で、その後の最適化が完了するのが翌日の6時頃という状況でした。バッチ処理を動かしているインスタンスのスケールアップにより多少の短縮は可能ですが、今後の更なる商品増加を考慮すると根本的な対応を講じる必要がありました。今回、上述したシステム構成を組むことでElasticsearchへのデータ投入処理はデータの最適化を含めて毎日21時頃に完了し、0時のデータ切り替え(公開)に間に合うようになりました。

13.5時間 → 4.5時間 データ更新時間を約67%短縮!!
処理時間を短縮できた要因には以下があります。

  1. Dataflowやその内部でBigQuery Storage APIを用いてElasticsearchのデータ変換処理を並列化したこと
  2. 検索用の商品情報(Elasticsearch)とサイトに表示する商品情報(Spanner)に分離したことで、Elasticsearchに投入するデータサイズを削減したこと
  3. Elasticsearchのシャードを2つに分割することで、投入データの処理を並列化したこと
  4. 検索用とデータ投入用のElasticsearchをそれぞれ用意することで、検索パフォーマンスの低下を気にせず投入データの処理に十分なマシンリソースを割り当てていること

その他細かな工夫は他にもありそうですが、大きくは上記の4つが挙げられます。
検索システムの移行に際しては、日次更新の時間短縮と検索レイテンシの維持、検索仕様の改善といった課題があり、そのどれもを満たせる仕組みを設計・実装しました。検索仕様の改善については今後、別の記事にてご紹介する予定です。

今後の取り組み予定

現状はECサイトの検索ページのみを新しい検索システムに置き換えた状態で、他のページでは従来の検索システムのままになっています。現在は検索ページ以外の移行を設計・実装を進めており、将来的には特集ページやレビューページ等でも通常の商品検索と同等の検索機能を持たせられるように検討しています。
また、検索ページの移行に関してもまだ3つの大きな課題が残っており、順次解決していく予定です。

  1. 商品データの投入完了までの処理時間の更なる短縮 => 商品データベースの最終更新時刻の延長
    0時に新しい商品データを検索できるように、16時に日次更新を開始しています。そのため、翌日にECサイトに反映させたい商品情報は16時までに商品データベース上で更新されなければいけません。これを当社の業務終了時間の18時まで延長したいと考えています。2時間延長するためには現状の21頃完了だとあまり余裕がなく、商品数の増加によって0時に間に合わなくなる可能性があるため、投入完了までにかかる時間をあと1時間程度早くする必要があります。

  2. 商品データの差分更新 => 商品のリアルタイム更新
    1の延長ですが、商品情報をリアルタイムに更新したいということも設計当初から検討し、残っている課題です。比較的現実的な落としどころとしては、まずは1日に数回(数時間に1回)の頻度で商品差分を更新していくことを実現したいと考えています。

  3. GCPマネージドサービス活用によるワークフローの改修 => 運用負荷の軽減、機能拡張性の向上
    GCEで実行しているバッチ用インスタンスや各ワークフロー間の強い依存関係をできるだけ減らせるようマネージドサービスを活用することで、運用負荷の軽減や1や2のような将来の実装に向けた拡張性の向上につなげていきたいと考えています。

「GCPマネージドサービス活用によるワークフローの改修」について、もう少し詳しく記載します。現在Elasticsearchデータ変換・データ投入箇所の設計検討中で、現時点の変更案を簡単にご紹介します。 上記のようにバッチスクリプトの動作環境として利用しているGCEインスタンスを大まかに以下のようなWorkflowsに置き換えたいと考えています。

  • 商品データ変換バッチ用Workflows
    ③-a Spannerデータ投入 と ③-b Elasticsearchデータ変換 のDataflowの実行を管理するワークフロー
  • Elasticsearchデータ投入バッチ用Workflows
    ④-a 投入用Elasticsearchへのデータ投入 から ④-b スナップショットの作成 までを実行するワークフロー
  • エイリアス切り替えバッチ用Workflows
    ⑤-a 検索用Elasticsearchへのデータリストア と ⑤-b 0時のエイリアスの切り替え を実行するワークフロー

また、③-b Elasticsearchデータ変換 の出力先をGCSからBigQueryに変更し、④-a Elasticsearchデータ投入 でLogstashインスタンスを起動する代わりにDataflowを利用する構成を検討しています。

まとめ

今回はMonotaROでのElasticsearchを使用した商品データの日次更新のシステム構成と工夫についてご紹介しました。検索システムでは大量の商品点数でも運用できるようにデータ投入の改善を進めていましたが、まだまだ改善点や新規の設計・実装などがあり、上記の取り組みに興味がある方はぜひカジュアルMTGに申し込みください!

*1:検索ページ以外で表示される商品情報にはまだSolrを利用しています。