ドキュメントの読み書き
はじめに
Elasticsearchの各インデックスは[$4ee358697c9c3f9a.md]で説明されているように[シャードに分割され]、各シャードは複数のコピーを持つことができます。これらのコピーはレプリケーショングループとして知られ、ドキュメントが追加または削除されるときに同期を保つ必要があります。これを怠ると、1つのコピーからの読み取り結果が別のコピーからの読み取り結果と大きく異なることになります。シャードコピーを同期させ、そこから読み取りを提供するプロセスをデータレプリケーションモデルと呼びます。
Elasticsearchのデータレプリケーションモデルはプライマリ-バックアップモデルに基づいており、Microsoft Researchの[https://www.microsoft.com/en-us/research/publication/pacifica-replication-in-log-based-distributed-storage-systems/]の[PacificA論文]で非常によく説明されています。このモデルは、レプリケーショングループからの単一のコピーがプライマリシャードとして機能することに基づいています。他のコピーは*レプリカシャード*と呼ばれます。プライマリはすべてのインデックス操作の主要なエントリポイントとして機能します。プライマリはそれらを検証し、正しいことを確認する責任があります。インデックス操作がプライマリによって受け入れられると、プライマリは他のコピーに操作をレプリケートする責任も負います。
このセクションの目的は、Elasticsearchのレプリケーションモデルの概要を提供し、書き込み操作と読み取り操作のさまざまな相互作用に対する影響を議論することです。
基本的な書き込みモデル
Elasticsearchのすべてのインデックス操作は、最初にルーティングを使用してレプリケーショングループに解決され、通常はドキュメントIDに基づいています。レプリケーショングループが決定されると、操作はグループの現在のプライマリシャードに内部的に転送されます。このインデックスの段階はコーディネーティングステージと呼ばれます。
インデックスの次の段階はプライマリステージで、プライマリシャードで実行されます。プライマリシャードは操作を検証し、他のレプリカに転送する責任があります。レプリカがオフラインの場合、プライマリはすべてのレプリカにレプリケートする必要はありません。代わりに、Elasticsearchは操作を受け取るべきシャードコピーのリストを維持します。このリストは同期コピーと呼ばれ、マスターノードによって維持されます。名前が示すように、これらはユーザーに承認されたすべてのインデックスおよび削除操作を処理したことが保証されている「良好な」シャードコピーのセットです。プライマリはこの不変性を維持する責任があり、このセット内の各コピーにすべての操作をレプリケートする必要があります。
プライマリシャードはこの基本的なフローに従います:
- 1. 受信操作を検証し、構造的に無効な場合は拒否します(例:数値が期待される場所にオブジェクトフィールドがある)。
- 2. 操作をローカルで実行します。つまり、関連するドキュメントをインデックスまたは削除します。これにより、フィールドの内容も検証され、必要に応じて拒否されます(例:キーワード値がLuceneでインデックス化するには長すぎる)。
- 3. 現在の同期コピーセット内の各レプリカに操作を転送します。複数のレプリカがある場合、これは並行して行われます。
- 4. すべての同期レプリカが操作を正常に実行し、プライマリに応答したら、プライマリはクライアントにリクエストの成功を確認します。
各同期レプリカコピーは、ローカルでインデックス操作を実行してコピーを持つようにします。このインデックスの段階はレプリカステージです。
これらのインデックスステージ(コーディネーティング、プライマリ、レプリカ)は順次です。内部的な再試行を可能にするために、各ステージのライフタイムは各次のステージのライフタイムを含みます。たとえば、コーディネーティングステージは、異なるプライマリシャードに分散している可能性のある各プライマリステージが完了するまで完了しません。各プライマリステージは、同期レプリカがローカルでドキュメントのインデックスを完了し、レプリカリクエストに応答するまで完了しません。
障害処理
インデックス作成中に多くのことが間違う可能性があります。ディスクが破損する、ノードが互いに切断される、または構成ミスにより、プライマリでは成功しているにもかかわらずレプリカで操作が失敗する可能性があります。これらは稀ですが、プライマリはそれに応答する必要があります。
プライマリ自体が失敗した場合、プライマリをホストしているノードは、マスターにその旨のメッセージを送信します。インデックス操作は、マスターがレプリカの1つを新しいプライマリに昇格させるのを待ちます(デフォルトで最大1分)。その後、操作は新しいプライマリに転送されて処理されます。マスターはノードの健康状態も監視しており、プライマリを積極的に降格させることを決定する場合があります。これは通常、プライマリを保持しているノードがネットワークの問題でクラスターから孤立しているときに発生します。詳細についてはこちらを参照してください。
操作がプライマリで正常に実行された後、プライマリはレプリカシャードで実行する際の潜在的な障害に対処する必要があります。これは、レプリカでの実際の障害や、操作がレプリカに到達するのを妨げるネットワークの問題(またはレプリカが応答するのを妨げる)によって引き起こされる可能性があります。これらすべては、同期レプリカセットの一部であるレプリカが、承認される直前の操作を見逃すという同じ最終結果を共有します。不変性を侵害しないようにするために、プライマリはマスターにメッセージを送信し、問題のあるシャードを同期レプリカセットから削除するよう要求します。シャードの削除がマスターによって承認されるまで、プライマリは操作を承認しません。マスターはまた、システムを健康な状態に戻すために、新しいシャードコピーの構築を開始するように別のノードに指示します。
操作をレプリカに転送する際、プライマリはレプリカを使用して自分がまだアクティブなプライマリであることを検証します。プライマリがネットワークパーティション(または長いGC)によって孤立している場合、降格されたことに気づく前に、受信したインデックス操作を処理し続ける可能性があります。古いプライマリからの操作はレプリカによって拒否されます。プライマリが、もはやプライマリではないためにリクエストを拒否するレプリカからの応答を受け取ると、マスターに連絡し、置き換えられたことを知ります。その後、操作は新しいプライマリにルーティングされます。
レプリカがない場合はどうなりますか?
これは、インデックスの構成や単にすべてのレプリカが失敗したために発生する可能性のある有効なシナリオです。その場合、プライマリは外部の検証なしで操作を処理しており、問題があるように見えるかもしれません。一方、プライマリは他のシャードを自分自身で失敗させることはできませんが、マスターにその代わりにそうするように要求できます。これは、マスターがプライマリが唯一の良好なコピーであることを知っていることを意味します。したがって、マスターが他の(古い)シャードコピーを新しいプライマリに昇格させることはなく、プライマリにインデックスされた操作が失われることはありません。もちろん、その時点でデータの単一コピーのみを実行しているため、物理的なハードウェアの問題がデータ損失を引き起こす可能性があります。いくつかの緩和オプションについてはアクティブシャードを参照してください。
基本的な読み取りモデル
Elasticsearchでの読み取りは、IDによる非常に軽量なルックアップや、非トリビアルなCPUパワーを要する複雑な集約を伴う重い検索リクエストになる可能性があります。プライマリ-バックアップモデルの美しさの1つは、すべてのシャードコピーが同一であることです(進行中の操作を除く)。そのため、単一の同期コピーで読み取りリクエストを処理するのに十分です。
ノードが読み取りリクエストを受信すると、そのノードは関連するシャードを保持するノードにリクエストを転送し、応答を集約し、クライアントに応答する責任があります。このノードをそのリクエストのコーディネーティングノードと呼びます。基本的なフローは次のとおりです:
- 1. 読み取りリクエストを関連するシャードに解決します。ほとんどの検索は1つ以上のインデックスに送信されるため、通常はデータの異なるサブセットを表す複数のシャードから読み取る必要があります。
- 2. シャードレプリケーショングループから、各関連シャードのアクティブなコピーを選択します。これはプライマリまたはレプリカのいずれかです。デフォルトでは、Elasticsearchは適応レプリカ選択を使用してシャードコピーを選択します。
- 3. 選択したコピーにシャードレベルの読み取りリクエストを送信します。
- 4. 結果を結合して応答します。IDによる取得の場合、関連するシャードは1つだけであり、このステップはスキップできます。
シャードの障害
シャードが読み取りリクエストに応答できない場合、コーディネーティングノードは同じレプリケーショングループ内の別のシャードコピーにリクエストを送信します。繰り返しの失敗により、利用可能なシャードコピーがなくなる可能性があります。
迅速な応答を確保するために、次のAPIは1つ以上のシャードが失敗した場合に部分的な結果で応答します:
部分的な結果を含む応答は、200 OK
HTTPステータスコードを提供します。シャードの障害は、応答ヘッダーのtimed_out
および_shards
フィールドによって示されます。
いくつかの単純な影響
これらの基本的なフローは、Elasticsearchが読み取りと書き込みの両方のシステムとしてどのように機能するかを決定します。さらに、読み取りリクエストと書き込みリクエストは同時に実行できるため、これら2つの基本的なフローは相互に作用します。これにはいくつかの固有の影響があります:
- 効率的な読み取り
- 通常の操作の下では、各読み取り操作は関連するレプリケーショングループごとに1回実行されます。障害条件の下でのみ、同じシャードの複数のコピーが同じ検索を実行します。
- 未承認の読み取り
- プライマリが最初にローカルでインデックスを作成し、その後リクエストをレプリケートするため、同時に行われる読み取りが承認される前に変更をすでに見る可能性があります。
- デフォルトで2つのコピー
- このモデルは、データのコピーを2つだけ維持しながら耐障害性を持つことができます。これは、耐障害性のための最小コピー数が3であるクォーラムベースのシステムとは対照的です。
障害
障害が発生した場合、次のことが可能です:
- 単一のシャードがインデックス作成を遅くする
- プライマリは各操作中に同期コピーセット内のすべてのレプリカを待つため、単一の遅いシャードが全体のレプリケーショングループを遅くする可能性があります。これは、上記の読み取り効率のために支払う代償です。もちろん、単一の遅いシャードは、それにルーティングされた不運な検索も遅くします。
- ダーティリード
- 孤立したプライマリは、承認されない書き込みを露出させる可能性があります。これは、孤立したプライマリがレプリカにリクエストを送信するか、マスターに連絡するまで孤立していることに気づかないために発生します。その時点で、操作はすでにプライマリにインデックスされており、同時に行われる読み取りによって読み取られる可能性があります。Elasticsearchは、デフォルトで毎秒マスターにpingを送り、マスターが知られていない場合はインデックス操作を拒否することでこのリスクを軽減します。
氷山の一角
この文書は、Elasticsearchがデータをどのように処理するかの高レベルの概要を提供します。もちろん、内部ではさらに多くのことが進行中です。プライマリターム、クラスター状態の公開、マスター選挙などが、このシステムが正しく機能するために重要な役割を果たしています。この文書では、既知の重要なバグ(クローズドおよびオープンの両方)についてもカバーしていません。GitHubは追跡が難しいことを認識しています。これらを把握するために、私たちは専用の[https://www.elastic.co/guide/en/elasticsearch/resiliency/current/index.html]を維持しています。ぜひお読みいただくことをお勧めします。