Elasticsearchのスケーラビリティ向上 ― 刷新された3つのポイント

blog-thumb-elasticsearch-scalability.jpg
icon-quote

「人は克服しようとして限界を発見する」

ハーバート・A・サイモン

Elasticは大規模な運用性と関連性にすぐれた高速な検索結果を通じて、ユーザーにバリューを届けることを重視しています。言い換えれば、ElasticのDNAには、スピードスケール関連性が刻まれています。Elasticsearch 7.16では特にスケールが焦点でした。7.16ではElasticsearchの性能が大きく向上し、これまで以上に検索が高速になり、メモリ消費量が下がって、クラスターが安定化しています。ここのところElasticはシャーディングのさまざまな側面の解明に取り組んでいました。そのプロセスの中で、私たちはElasticsearchを新たな水準のスピードに到達させることに成功したのです。 

かつてElasticは、リソースのオーバーヘッドという観点からクラスターに膨大すぎる数のシャードを作成しないというアプローチを推奨していました。しかし、Fleetを使う最新のデータストリームインデックスストラテジーを活用すると、セキュリティからオブザーバビリティまでユースケースを問わず、より小さなシャードが多数生成されます。このため、増加し続けるシャードに対処する新しいアプローチが必要になりました。本ブログ記事は、スケーリングに伴ってElasticsearchに生じる3つの課題と、7.16以降のElasticsearchエクスペリエンスを向上させたメカニズムについて説明します。 

Video thumbnail

認可を合理化する

パブに入店する場面について考えてみましょう。はじめに入り口でIDのチェックを受け、その後も、飲み物を注文するたびにIDを提示する必要があります。7.15以前で認可を実行する仕組みがこれでした。つまり、すべてのノード(入り口)で認可のチェックが必須で、さらにすべてのシャード(飲み物の注文)について認可のチェックを求めていました。しかし、入り口で1回だけIDチェックを行い、注文時のチェックもそれで済んだことにすると、どうなるでしょうか?このアイデアをElasticsearchにあてはめて考えてみましょう。

Elasticsearchでは、ユーザーがロール/属性ベースのアクセス制御を設定することにより、フィールド別やドキュメント別、インデックスレベル別にきめ細かい権限を付与できます。かつては検索クエリの多数のフェーズで認可を確認することにより、権限のないデータへのアクセスを確実に防止していました。認可による厳しい警戒はコストがかさみますが、クラスターサイズが大きくなるにつれ、このロジックの一部は水平にスケールしなくなります。 たとえば大きなクラスターのすべてのインデックスとすべてのフィールドにフィールド機能を持たせると、認可関連の作業に実行時間のほぼすべてが費やされ、完了までに何十秒、あるいは何分もかかる可能性があります。

7.16は、この問題を2つの側面から解消しています。

  1. Elasticは認可アルゴリズムを改善し、RESTリクエストとElasticsearchクラスター内のノード間の転送レイヤーの通信の認可の両方で、個々のリクエストの認可を高速化しました。
  2. 内部リクエストが以前のチェックから引き継がれる場合も、作成される場合にも、多くのケースで認可コストを大幅に下げました。7.15以前は、Elasticsearchがクラスター内で内部転送リクエストを認可する時、最初の外部リクエストがパスしたものと同じ認可ロジックを実行していました。これは、攻撃者が認可のロジックをバイパスして内部リクエストを作成し、ノードツーノードの内部通信へ攻撃面を持ち込む事態を回避するためでした。7.16以降は、サブリクエストのワイルドカード拡張のスキップに加え、同じノード内の“ノードローカル”なリクエストの認可のスキップ、および、検索などのアクションに必要なリクエストの総数を減らすことによって、コストが大幅に下がっています。

プリフィルターフェーズのシャードリクエストを減らす

7.16ではプリフィルターフェーズに新しい検索ストラテジーを実装しており、一致するノードあたりのリクエスト数が減って、1回だけになりました。7.15以前、検索の最初のフェーズで関連データを含まないことが判明しているすべてのシャードをクエリから除外するには、調整ノードからデータノードまでのシャード1つにつき1つのリクエストが必要でした。数千のシャードに同時にクエリをかける場合、必然的に、調整ノードから検索リクエスト1つにつき数千ものリクエストを送信することになり、また調整ノードで数千ものレスポンスを処理したり、データノードでこのリクエストを処理して応答したりする必要がありました。クラスターをスケールしてデータノードの数を増やせば、データノードで多数のリクエストを処理するパフォーマンスは向上しますが、調整ノードでの動作のパフォーマンスには役立ちません。

プリフィルターフェーズで実行するストラテジーを変更した7.16以降は、このフェーズでノード1つにつき1つのリクエストだけが送信され、ノード上のすべてのシャードがカバーされます。その変化を具体的に示したものが、下の図1です。たとえば3つのデータノード全体で数千のシャードを保持している場合、検索対象となるシャードの数に関わらず、最初の検索フェーズで発生するネットワークリクエストの数が数千から3以下に減少します。7.15以前は、シャード毎にリクエスト(つまり検索クエリ)が送られていましたが、全シャードでほぼ同じデータが送られていました。これに対し、1ノードに1つのリクエストを送る場合は、複数のリクエストにわたる情報の重複がなくなり、ネットワーク全体で送信されるデータ量が劇的に低下します。

`プリフィルター`フェーズで実行するストラテジーを変更した7.16以降は、このフェーズでノード1つにつき1つのリクエストしか送信されず、ノード上のすべてのシャードがカバーされる。
図1. 7.15以前と7.16以後の分散フェーズの違い

Elasticは、Kibanaと*QLクエリが使用するfield_capsについても同様の変更を実施しました。理論的には、ネットワークリクエストで減らせる検索リクエストは、1クエリにつきO(シャード)からO(ノード)であるはずです。しかし実際にベンチマークテストを行って、大規模なロギングクラスターにある数か月分のログをクエリしたところ、数分から数秒へと短縮されるという結果が得られました。この変更は、ネットワークリクエストの数だけでなく、リクエストに関連するメモリやCPUの使用量の削減に役立っていると考えられます。

メモリのフットプリントを減らす

信じがたいことに、全員のサラダからオリーブを1つ減らしたり、眼鏡をスリムにしたり、紙の雑誌のサイズを小さくするだけで航空会社は飛行機の積載重量を大幅に減らすことができます。私たちはフィールドごとのメモリコストの削減という形で、これと同様のアプローチをElasticsearchに導入しました。1フィールドあたりではわずか数キロバイトの減少ですが、クラスター内のすべてのインデックスに存在する数百万ものフィールドで削減することにより、莫大なヒープ使用量の減少を実現させました。

Elasticsearchデータノードにおけるヒープ使用量は、インデックス数と、インデックスあたりのフィールド数、クラスターステータスに格納されるシャード数に依存します。インデックス数が増えると、ノードの負荷に関わらず、ヒープ領域が常に使用されることになります。Elasticは7.16でテキストフィールドとフィールドのフィールドビルダーを再構築しました。この結果メモリのフットプリントが減少し、このフィールド構造の保持だけに使われていたメモリを90%以上削減しました。 

インジェスト、検索した結果…勝利を確認

7.16は一般提供されており、私たちは現実的なワークロードを実行するクラスターを使ってこの性能向上を実際に観測することができます。下の複数のグラフは、60本のデータノードがあるクラスターを7.16にアップグレードした際の効果を示したものです。

figure1
図2. 7.15以前と7.16以後の検索レイテンシー比較(値が小さいほど良い)
figure2
図3. 7.15以前と7.16以後の検索レート(値が大きいほど良い)
figure3
図4. 7.15以前と7.16以後のFrozenノードにおけるヒープ使用率(値が小さいほど良い)
figure4
図5. 7.15以前と7.16以後のyoung GC比較(値が小さいほど良い)
figure5
図6. 7.15以前と7.16以後のマスターノードにおけるCPUスロッティング(値が小さいほど良い)

このクラスターには、アップグレードの前後を通じて安定的なワークロードが見られます。一方で、検索レイテンシーは一律に99パーセンタイル減少し、検索レート(スループット)が向上しているほか、データストラクチャー格納にかかるメモリのフットプリントの減少と共にFrozenノードのヒープ使用量が一貫して低下しています。この変化はすべてのデータティアに影響があると予想できますが、最も顕著に影響が表れるのはFrozenティアです。インデックスやクエリなど他のアクティビティにもヒープが使われるHotノードとは異なり、Frozenティアでは、ヒープを主にデータストラクチャーの格納に使用するためです。ノードロール別に見ると、調整ノードはプリフィルターフェーズにおけるシャードリクエストの減少の恩恵を受けて、最も顕著にyoung GCカウントが減少しています。また、クラスター状態の管理性の向上に伴い、マスターノードにおけるCPUスロッティング要求が大幅に減少しています。

Elasticはシャードを数万にスケーリングした場合にElasticsearchのパフォーマンスに生じる問題の原因調査を行い、Elasticsearch 7.16のリリースではスケーラビリティの向上に照準を定めてきました。 膨大な数のシャードの作成とマッピングの爆発的増加はElasticsearchをクラッシュさせる最もよくある要因として知られており、今なおいずれも回避しなければなりません。しかし、7.16で性能向上が実現したことにより、予期される影響はかなり小さくなりました。今回のリリースの性能向上ではクラスター全体のサイズに比重が置かれています。つまりクラスターステータスの更新をより小さいサイズのマスターで処理することが可能になり、多数のインデックス全体の検索コーディネーションが効率化されました。

生まれ変わったElasticsearch 7.16のパワーを解き放つことにより、既存の検索エンジンのスピードが上がり、メモリ要件が下がって、クラスターの安定性が向上します。必要な作業は…アップグレード。それだけです!Elasticはスケーラビリティの最前線に立ち、さまざまな側面から継続して性能向上に取り組んでいます。近日公開の8.xについても、改めてお知らせを予定しています。

さっそくスケールする

Elastic Cloudをご利用中のお客様は、ご紹介した機能にElastic Cloudコンソールから直接アクセスできます。Elastic Cloudの導入をご検討中の方は、導入に最適な短いトレーニングビデオ「Quick Start guides」(クイックスタートガイド)や、Elasticが提供する無料の基礎コースをご利用いただけます。Elasticは、Elastic Cloudの14日間無料トライアルを常時ご用意しています。また、セルフマネージド版のElastic Stackを無料でダウンロードしてお使いいただくこともできます。

ご紹介した性能向上やその他の機能について詳しくは、Elastic 7.16リリースノートをご覧ください。Elastic Stackのその他のハイライトについては、Elastic 7.16リリースブログ記事で詳しく取り上げています。