<-- mermaid -->

Elasticsearchの検索速度低下を調査してEBS Volumeタイプを変更したら高速化できました

こんにちは。NewsPicksでエンジニアをやっております崔(チェ)です。現在は Data / Algorithm チームで検索エンジンの開発を担当しております。この半年間、検索に関しては色々と改善しており、去年までと比較し大きく使いやすくなったのではないでしょうか。前回の記事では検索精度改善に関するお話をしましたので、今回は検索速度を改善したお話をしようと思います。ご興味ある方は是非読んでいただけると嬉しいです。

ことの背景

問題発生

前回の改善報告にあるように、先月、拾う品詞を拡大・形態素解析の方法を変更するなどの改善を行いました。これにより基本的な検索の精度は向上したのですが、社内から「リリース後から「マイピックス」(自分のPickした記事)の検索速度が遅くなっているように感じるので調べてほしい」とお問い合わせが来るようになりました。

上記のリリースが問題の原因なのかをまず確認する必要がありました。検索してから結果を返すまでの所要時間をパーセンタイルにして調べました。すると、95パーセンタイル(95%の観察結果)が、リリース日を基準に明確に右肩上がりのグラフになっており、最も遅いときは11秒までかかっていることがわかりました。

前回リリース前後のマイピックスの検索速度のパーセンタイル(95%)
一方で、トップ画面での記事検索の結果を返すまでの所要時間は、リリース前後であまり差は見られませんでした。
前回リリース前後の記事(Topタブ)の検索速度のパーセンタイル(95%)

原因を考えてみる

上記のリリースにより1つのドキュメントが持つトークンが増えたため、各インデックスのサイズも大きくなりました。その分、検索時にデータを読み込む際、時間がかかるようになったのかもしれません。特に、お問い合わせがあったマイピックスは、複数のインデックスを組み合わせて検索を行います。上のグラフで分かるように、トップ画面で記事を検索するなど、1つのインデックスだけを探索するケースと比較すると、その影響を更に受けたというのも自然です。

ですが、果たしてこれは今回マイピックスの速度低下のクリティカルな原因なのでしょうか?Elasticsearch(以下 ES)の検索速度改善に関するドキュメントでは第一にメモリーを確保すること、第二にデータの読み書きの速度が早いSSDを使うことを順に推奨していました。

Give memory to the filesystem cache

Elasticsearch heavily relies on the filesystem cache in order to make search fast. In general, you should make sure that at least half the available memory goes to the filesystem cache so that Elasticsearch can keep hot regions of the index in physical memory.

Use faster hardware

If your searches are I/O-bound, consider increasing the size of the filesystem cache (see above) or using faster storage. Each search involves a mix of sequential and random reads across multiple files, and there may be many searches running concurrently on each shard, so SSD drives tend to perform better than spinning disks.

Elasticsearchの検索では、ファイルシステムのランダムアクセスが多用されるため、HDDよりSSDの方が高速なことが多いためです。

前置きとして、現在NewsPicksでは検索エンジンをAmazon EC2 Instance(以下 Instance)で稼働しております。

確認事項1.十分なメモリーが確保できているか

メモリーを確認した結果、半分以上占めておりましたが、空き容量がありました。

確認事項2.SSDを使用しているか

次に、どのAWS EBS Volume(以下 Volume)がアタッチされているかですが、もしSSDのものであれば、ある程度のデータの読み書きの速度は保たれているはずです。なので、メモリをさらに確保するか、インデックスのサイズを減らすなどの別の施策を考える必要があります。

確認してみると、なんと、Magnetic(standard)というVolumeの中でも最も古いタイプのHDD(AWSのドキュメントによると、Magneticは「以前世代のVolume」として扱われていました)がアタッチされいることが判明しました。その上、Magneticの想定されるユースケースは「あまりデータを探索しないケース」らしいので、NewsPicksの用途とは随分離れているVolumeタイプということがわかります。

EBS Magnetic volumes are backed by hard disk drives (HDDs) and can be used for workloads with smaller datasets where data is accessed infrequently or when performance consistency isn’t of primary importance.

やはり根本的な原因は、Magneticという検索システムに適合していない以前世代のHDDのVolumeを使用していたことであり、稼働中のInstanceのVolumeをSSDに差し替える必要があります。

対策を考える

SSDのVolumeは、gp3 / gp2 / io2 Block Express / io2があるのですが、io2 Block Expressとio2は今回の場合オーバースペックですので考慮しません。

以下のテーブルはMagnetic(standard)と、gp3 / gp2のスペックを比較したものです。

ドライブタイプ Volumeタイプ ユースケース 最大IOPS / Volume 最大スループット / Volume
HDD standard データに頻繁にアクセスしないワークロード 40–200 40–90 MiB/s
SSD gp2
  • トランザクションワークロード
  • 仮想デスクトップ
  • 中規模の単一インスタンスデータベース
  • 低レイテンシーのインタラクティブなアプリケーション
  • ブートボリューム
  • 開発・テスト環境
16,000 250 MiB/s
(スループット制限:ボリュームサイズに応じて128Mib/秒~250Mib/秒)
gp3 1,000 MiB/s

  • IOPS:HDDやSSDなどのストレージ(外部記憶装置)の性能指標の一つで、ある条件の元で1秒間に読み込み・書き込みできる回数を指します。IOPSの値が高いほど高速にデータの読み書きができることを表します。
  • スループット:単位時間あたりに処理できるデータ量のことです。
  • トランザクションワークロード:データベースに頻繁にアクセスし高速にやりとりをするケースです。
  • 仮想デスクトップ:1つのディスプレイで複数のデスクトップを利用するための機能です。
  • レイテンシー:データ転送における指標であり、リクエストされてからレスポンスを返すまでの通信の遅延時間を指します。
  • ブートボリューム:システムブート用のボリュームで、ブートとはコンピューターの電源を入れシステムを利用可能な状態にすることです。

費用調査

各Volumeタイプごとの性能も重要ですが、現実的に予算を考える必要もありました。以下の計算結果は、AWS Pricing Calculatorで計算した結果です。Instanceを1台使用し、そのInstanceタイプと費用戦略を同一にして計算しました。InstanceにアタッチするVolumeタイプによる費用変化を確認するためです。

ご覧の通り、Amazon EC2 Instanceのコストから比べるとAmazon EBS Volumeによるコスト差はほぼありませんでした。gp3のデフォルトスペック(IOPS:3,000 / スループット:125MBps)でstandardより遥かに良い性能で、gp2と比べても安かったため、gp3に変更することにしました。

Volumeタイプ Instanceタイプ EC2オンデマンドInstance費用 / 月(USD) EBS費用 / 月(USD) 合計(USD)
standard m4.xlarge
  • メモリ:16GB
  • vCPUs:4
1,88.34 8.00 196.34
gp2 12.00 200.34
gp3 9.60 197.94

ちなみに、standardとgp2はIOPSやスループットなどのスペックが選択できません。gp3はスペックのカスタムができ、デフォルトスペックが最低値ではありません。

検証

稼働中のInstanceのVolumeを差し替える方法を確認

実は、Volumeタイプを変更するためには、Instanceごと差し替える必要があるのではないかと思っていたのですが、調べてみると、2021年4月から稼働中のInstanceをリブートすることなくVolumeだけ差し替えることが可能になっていました。

Amazon EC2 announces the Replace Root Volume feature that enables customers to replace the root volume for a running instance. The feature restores the root volume of an instance to its launch state, or to a specific snapshot, without stopping the instance. The Replace Root Volume feature is available in all public AWS Regions and AWS GovCloud (US) Regions.

上記のAWSが紹介している変更方法NewsPicksのケースでも安全に使えるか確認する必要がありました。下記の懸念事項を潰すべく、まずは開発環境でVolumeを差し替えてみました。実際のリリース手順は、下で詳しく述べていきます。

  • 差し替えにかかる時間
  • 差し替え中に検索機能は使えるか
  • 差し替え中に検索速度が著しく低下したりしないか
  • 差し替え中に検索データを追加・更新・削除することは可能か
  • 以前世代のVolumeであるMagneticもModify Volumeを利用して差し替えることが可能か

わかったこととしては以下があります。

  • 差し替え開始から完了までは、Volumeのサイズに関係なく(60GBと100GBで実験)約2時間かかる
  • 差し替えが完了していなくてもKibanaを介したESとのやりとりが可能
    • 検索可能
    • ドキュメント・インデックスの追加・削除が可能
  • 差し替え中であってもESへリクエストしてレスポンスを受け取るまでの時間は変化なし
    • 連続して検索する場合も同様
  • Volumeのステータスが in-use になっていない間(差し替えが完了していない間)は、別のVolumeタイプに変更することが不可能(以下の図を参照)

速度検証

上記で述べたように、ESではにSSDにすることで高速化できると紹介していますが、実際どれほどデータの読み書きが早くなるのか開発環境で実験してみました。以下の検証結果はVolumeのステータスが in-use になってから計測したものであり、APIの実行と結果取得はKibanaを用いて行いました。

使用したデータ 実行したAPI 結果を返すまでの時間
standard gp3
  • インデックス数:1
  • ドキュメント数:約1,900万件
search(10回平均) 約195.4 mesc 約1.7 mesc
  • インデックス数:2
  • ドキュメント数:約1,900万件 / 約1,700万件
search(10回平均) 約487.7 mesc 約3.8 mesc
  • インデックス数:1
  • ドキュメント数:約1,900万件
reindex
  • slices:auto
  • await_for_completion:false
約5時間18分 約5時間
  • インデックス数:1
  • ドキュメント数:約1,900万件
restore
  • include_global_state:true
約30分 約15分

肝心の検索速度ですが、同じクエリでも毎回の所要時間が異なるので一概には言えません。ただ、今回の実験だと、1つのインデックスだけを使用した場合は約110倍早くなり、2つのインデックスを使用した場合は約130倍早くなりました。 検索速度以外にもデータ復元速度や、再インデックスする時間も短縮できました。

リリース

検証の結果からわかるように、standardからgp3にModify Volumeするだけで差し替えは可能であり、問題だった検索速度も大幅に改善されることが確認できました。したがって、本番の検索用のInstanceのVolumeもModify Volume機能を使いgp3に差し替えました。

リリース手順

稼働中のInstanceのStorageからアタッチされているVolumeを選択します。

Amazon EBS Volume画面から上で選択したVolumeにチェックを入れ、Modify Volumeを実行します。

そうすると、以下のようなポップアップが浮かぶので、変更したいVolumeタイプを選択します。

もしVolumeタイプだけではなくサイズも変更する際は、以下の画面の注意事項から遷移できるドキュメントをご確認ください。ドキュメントによると、サイズを変更しても実際のファイルシステムを拡張する前までは使用不可の状態であり、パーティションのサイズは拡張されないらしいです。拡張方法に関してはドキュメントをご参照ください。

すべての設定が完了し、以下のような成功画面が出たらポップアップを閉じ、Volumeのステータスが in-use になることを確認してください。上でも述べましたが、in-useにならなくてもインスタンスは今まで通り使用できます。

結果

下の図は、本番で稼働中の全ての検索用のInstanceのVolumeタイプがgp3になる前後の検索速度を比較したグラフです。 変更前は、検索結果を返すのに遅い場合、約11秒までかかっていたマイピックスですが、変更後は95パーセンタイルが約0.7秒~約1.7秒に収まっていることが確認できます。

SSD使用後のマイピックスの検索速度パーセンタイル(95%)
マイピックスより前回のリリース直後の検索速度に変化がなかったTopタブですが、95パーセンタイルの数値が、SSDに変更してから約1.7秒ー>約1.3秒まで早くなっていることが確認できます。
SSD使用後の記事の検索速度パーセンタイル(95%)

最後に

皆さんは普段NewsPicksを利用しながらこの速度変化を体感できたでしょうか?

NewsPicksは今後も検索を含め色々改善してまいりますので、引き続きよろしくお願いいたします!

Page top