検索シャードルーティング

ハードウェアの故障から保護し、検索能力を向上させるために、Elasticsearchはインデックスのデータのコピーを複数のシャードにわたって複数のノードに保存できます。検索リクエストを実行する際、Elasticsearchはインデックスのデータのコピーを含むノードを選択し、そのノードのシャードに検索リクエストを転送します。このプロセスは検索シャードルーティングまたはルーティングとして知られています。

適応レプリカ選択

デフォルトでは、Elasticsearchは検索リクエストをルーティングするために適応レプリカ選択を使用します。この方法は、シャード割り当ての認識と以下の基準を使用して適格なノードを選択します:

  • 協調ノードと適格ノード間の以前のリクエストの応答時間
  • 適格ノードが以前の検索を実行するのにかかった時間
  • 適格ノードのsearch スレッドプールのキューサイズ

適応レプリカ選択は、検索のレイテンシを減少させるように設計されています。ただし、cluster.routing.use_adaptive_replica_selectionfalseに設定することで適応レプリカ選択を無効にすることができます。クラスタ設定APIを使用します。無効にすると、Elasticsearchはラウンドロビン方式で検索リクエストをルーティングし、検索が遅くなる可能性があります。

優先度を設定する

デフォルトでは、適応レプリカ選択はすべての適格ノードとシャードから選択します。ただし、ローカルノードからのデータのみを取得したい場合や、ハードウェアに基づいて特定のノードに検索をルーティングしたい場合があります。また、キャッシュを利用するために同じシャードに繰り返し検索を送信したい場合もあります。

検索リクエストに対して適格なノードとシャードのセットを制限するには、検索APIのpreferenceクエリパラメータを使用します。

たとえば、次のリクエストはmy-index-000001preference_localで検索します。これにより、検索はローカルノードのシャードに制限されます。ローカルノードにインデックスのデータのシャードコピーがない場合、リクエストは適応レプリカ選択を使用して別の適格ノードにフォールバックします。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. preference="_local",
  4. query={
  5. "match": {
  6. "user.id": "kimchy"
  7. }
  8. },
  9. )
  10. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. preference: '_local',
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => 'kimchy'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. preference: "_local",
  4. query: {
  5. match: {
  6. "user.id": "kimchy",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_search?preference=_local
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": "kimchy"
  6. }
  7. }
  8. }

提供された文字列に基づいて特定のシャードに検索をルーティングするために、preferenceパラメータを使用することもできます。クラスタの状態と選択されたシャードが変更されない場合、同じpreference文字列を使用した検索は、同じ順序で同じシャードにルーティングされます。

ユーザー名やウェブセッションIDなどのユニークなpreference文字列を使用することをお勧めします。この文字列は_で始めることはできません。

このオプションを使用して、頻繁に使用されるリソース集約型の検索に対してキャッシュされた結果を提供できます。シャードのデータが変更されない場合、同じpreference文字列を使用した繰り返し検索は、同じシャードリクエストキャッシュから結果を取得します。ログ記録などの時系列ユースケースでは、古いインデックスのデータはほとんど更新されず、このキャッシュから直接提供できます。

次のリクエストは、my-index-000001preference文字列のmy-custom-shard-stringで検索します。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. preference="my-custom-shard-string",
  4. query={
  5. "match": {
  6. "user.id": "kimchy"
  7. }
  8. },
  9. )
  10. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. preference: 'my-custom-shard-string',
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => 'kimchy'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. preference: "my-custom-shard-string",
  4. query: {
  5. match: {
  6. "user.id": "kimchy",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_search?preference=my-custom-shard-string
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": "kimchy"
  6. }
  7. }
  8. }

クラスタの状態や選択されたシャードが変更されると、同じpreference文字列が同じ順序で同じシャードに検索をルーティングしない可能性があります。これは、シャードの移動やシャードの故障など、さまざまな理由で発生する可能性があります。ノードは検索リクエストを拒否することもでき、その場合、Elasticsearchは別のノードに再ルーティングします。

ルーティング値を使用する

ドキュメントをインデックスする際に、特定のシャードにドキュメントをルーティングするオプションのルーティング値を指定できます。

たとえば、次のインデックスリクエストはmy-routing-valueを使用してドキュメントをルーティングします。

Python

  1. resp = client.index(
  2. index="my-index-000001",
  3. routing="my-routing-value",
  4. document={
  5. "@timestamp": "2099-11-15T13:12:00",
  6. "message": "GET /search HTTP/1.1 200 1070000",
  7. "user": {
  8. "id": "kimchy"
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.index(
  2. index: 'my-index-000001',
  3. routing: 'my-routing-value',
  4. body: {
  5. "@timestamp": '2099-11-15T13:12:00',
  6. message: 'GET /search HTTP/1.1 200 1070000',
  7. user: {
  8. id: 'kimchy'
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.index({
  2. index: "my-index-000001",
  3. routing: "my-routing-value",
  4. document: {
  5. "@timestamp": "2099-11-15T13:12:00",
  6. message: "GET /search HTTP/1.1 200 1070000",
  7. user: {
  8. id: "kimchy",
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. POST /my-index-000001/_doc?routing=my-routing-value
  2. {
  3. "@timestamp": "2099-11-15T13:12:00",
  4. "message": "GET /search HTTP/1.1 200 1070000",
  5. "user": {
  6. "id": "kimchy"
  7. }
  8. }

検索APIのroutingクエリパラメータで同じルーティング値を使用できます。これにより、検索がドキュメントをインデックスするために使用された同じシャードで実行されることが保証されます。

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. routing="my-routing-value",
  4. query={
  5. "match": {
  6. "user.id": "kimchy"
  7. }
  8. },
  9. )
  10. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. routing: 'my-routing-value',
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => 'kimchy'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. routing: "my-routing-value",
  4. query: {
  5. match: {
  6. "user.id": "kimchy",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_search?routing=my-routing-value
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": "kimchy"
  6. }
  7. }
  8. }

複数のカンマ区切りのルーティング値を提供することもできます:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. routing="my-routing-value,my-routing-value-2",
  4. query={
  5. "match": {
  6. "user.id": "kimchy"
  7. }
  8. },
  9. )
  10. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. routing: 'my-routing-value,my-routing-value-2',
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => 'kimchy'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. routing: "my-routing-value,my-routing-value-2",
  4. query: {
  5. match: {
  6. "user.id": "kimchy",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_search?routing=my-routing-value,my-routing-value-2
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": "kimchy"
  6. }
  7. }
  8. }

検索の同時実行性と並列性

デフォルトでは、Elasticsearchはリクエストがヒットするシャードの数に基づいて検索リクエストを拒否しません。ただし、大量のシャードにヒットすると、CPUとメモリの使用量が大幅に増加する可能性があります。

大量のシャードを持つインデックスを防ぐためのヒントについては、シャードのサイズを調整するを参照してください。

  1. #### Python
  2. ``````python
  3. resp = client.search(
  4. index="my-index-000001",
  5. max_concurrent_shard_requests="3",
  6. query={
  7. "match": {
  8. "user.id": "kimchy"
  9. }
  10. },
  11. )
  12. print(resp)
  13. `

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. max_concurrent_shard_requests: 3,
  4. body: {
  5. query: {
  6. match: {
  7. 'user.id' => 'kimchy'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. max_concurrent_shard_requests: 3,
  4. query: {
  5. match: {
  6. "user.id": "kimchy",
  7. },
  8. },
  9. });
  10. console.log(response);

コンソール

  1. GET /my-index-000001/_search?max_concurrent_shard_requests=3
  2. {
  3. "query": {
  4. "match": {
  5. "user.id": "kimchy"
  6. }
  7. }
  8. }

action.search.shard_count.limitクラスタ設定を使用して、検索シャードの制限を設定し、あまりにも多くのシャードにヒットするリクエストを拒否することもできます。[action.search.shard_count.limitを設定するには、クラスタ設定APIを使用します。