クラスター間検索
クラスター間検索を使用すると、1つまたは複数のリモートクラスターに対して単一の検索リクエストを実行できます。たとえば、クラスター間検索を使用して、異なるデータセンターに保存されているログデータをフィルタリングおよび分析できます。
サポートされているAPI
次のAPIはクラスター間検索をサポートしています:
- 検索
- 非同期検索
- マルチ検索
- 検索テンプレート
- マルチ検索テンプレート
- フィールド機能
- Painless実行API
- インデックス解決API
- [プレビュー] この機能は技術プレビュー中であり、将来のリリースで変更または削除される可能性があります。Elasticは問題を修正するために取り組みますが、技術プレビューの機能は公式GA機能のサポートSLAの対象ではありません。 EQL検索
- [プレビュー] この機能は技術プレビュー中であり、将来のリリースで変更または削除される可能性があります。Elasticは問題を修正するために取り組みますが、技術プレビューの機能は公式GA機能のサポートSLAの対象ではありません。 SQL検索
- [プレビュー] この機能は技術プレビュー中であり、将来のリリースで変更または削除される可能性があります。Elasticは問題を修正するために取り組みますが、技術プレビューの機能は公式GA機能のサポートSLAの対象ではありません。 ベクトルタイル検索
- [プレビュー] この機能は技術プレビュー中であり、将来のリリースで変更または削除される可能性があります。Elasticは問題を修正するために取り組みますが、技術プレビューの機能は公式GA機能のサポートSLAの対象ではありません。 ES|QL
前提条件
- クラスター間検索にはリモートクラスターが必要です。Elasticsearch Serviceでリモートクラスターを設定するには、Elasticsearch Serviceでのリモートクラスターの構成を参照してください。自分のハードウェアでElasticsearchを実行している場合は、リモートクラスターを参照してください。
リモートクラスターの構成がクラスター間検索をサポートしていることを確認するには、サポートされているクラスター間検索構成を参照してください。 - 完全なクラスター間検索機能を利用するには、ローカルクラスターとリモートクラスターが同じサブスクリプションレベルである必要があります。
ローカルコーディネーティングノードは、
remote_cluster_client
ノードロールを持っている必要があります。スニッフモードを使用する場合、ローカルコーディネーティングノードはリモートクラスターのシードノードおよびゲートウェイノードに接続できる必要があります。
コーディネーティングノードとして機能できるゲートウェイノードの使用をお勧めします。シードノードはこれらのゲートウェイノードのサブセットである可能性があります。プロキシモードを使用する場合、ローカルコーディネーティングノードは構成された
proxy_address
に接続できる必要があります。このアドレスのプロキシは、リモートクラスターのゲートウェイおよびコーディネーティングノードへの接続をルーティングできる必要があります。- クラスター間検索には、ローカルクラスターとリモートクラスターで異なるセキュリティ権限が必要です。クラスター間検索のための権限の構成およびリモートクラスターを参照してください。
クラスター間検索の例
リモートクラスターの設定
次のクラスター更新設定APIリクエストは、3つのリモートクラスターを追加します: cluster_one
、cluster_two
、cluster_three
。
Python
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"35.238.149.1:9300"
],
"skip_unavailable": True
},
"cluster_two": {
"seeds": [
"35.238.149.2:9300"
],
"skip_unavailable": False
},
"cluster_three": {
"seeds": [
"35.238.149.3:9300"
]
}
}
}
},
)
print(resp)
Ruby
response = client.cluster.put_settings(
body: {
persistent: {
cluster: {
remote: {
cluster_one: {
seeds: [
'35.238.149.1:9300'
],
skip_unavailable: true
},
cluster_two: {
seeds: [
'35.238.149.2:9300'
],
skip_unavailable: false
},
cluster_three: {
seeds: [
'35.238.149.3:9300'
]
}
}
}
}
}
)
puts response
Js
const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
cluster_one: {
seeds: ["35.238.149.1:9300"],
skip_unavailable: true,
},
cluster_two: {
seeds: ["35.238.149.2:9300"],
skip_unavailable: false,
},
cluster_three: {
seeds: ["35.238.149.3:9300"],
},
},
},
},
});
console.log(response);
コンソール
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"35.238.149.1:9300"
],
"skip_unavailable": true
},
"cluster_two": {
"seeds": [
"35.238.149.2:9300"
],
"skip_unavailable": false
},
"cluster_three": {
"seeds": [
"35.238.149.3:9300"
]
}
}
}
}
}
skip_unavailable がcluster_three に設定されていないため、false のデフォルトを使用します。詳細については、オプションのリモートクラスターセクションを参照してください。 |
単一のリモートクラスターを検索
検索リクエストでは、リモートクラスターのデータストリームとインデックスを<remote_cluster_name>:<target>
として指定します。
次の検索APIリクエストは、単一のリモートクラスターcluster_one
のmy-index-000001
インデックスを検索します。
Python
resp = client.search(
index="cluster_one:my-index-000001",
size=1,
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
Ruby
response = client.search(
index: 'cluster_one:my-index-000001',
body: {
size: 1,
query: {
match: {
'user.id' => 'kimchy'
}
},
_source: [
'user.id',
'message',
'http.response.status_code'
]
}
)
puts response
Js
const response = await client.search({
index: "cluster_one:my-index-000001",
size: 1,
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
GET /cluster_one:my-index-000001/_search
{
"size": 1,
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
APIは次の応答を返します。1つ以上のリモートクラスターを検索する場合、各クラスターでの検索に関する情報を提供するために_clusters
セクションが含まれます。
コンソール-結果
{
"took": 150,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total": 1,
"successful": 1,
"skipped": 0,
"running": 0,
"partial": 0,
"failed": 0,
"details": {
"cluster_one": {
"status": "successful",
"indices": "my-index-000001",
"took": 148,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"skipped": 0,
"failed": 0
}
}
}
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "cluster_one:my-index-000001",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
}
]
}
}
このカウンターのセクションは、すべての可能なクラスター検索状態と、現在その状態にあるクラスター検索の数を示しています。クラスターは次のいずれかのステータスのいずれかです:実行中、成功(すべてのシャードでの検索が成功した)、部分的(クラスターの少なくとも1つのシャードでの検索が成功し、少なくとも1つが失敗した)、スキップ(skip_unavailable =true でマークされたクラスターでの検索が失敗した)または失敗(skip_unavailable =false でマークされたクラスターでの検索が失敗した)。 |
|
_clusters/details セクションは、各クラスターでの検索に関するメタデータを示します。 |
|
ユーザーが提供したインデックス式。ワイルドカードlogs-* のようなものを提供した場合、このセクションは具体的に検索されているインデックスではなく、ワイルドカードを含む値を表示します。 |
|
そのクラスターでのサブ検索にかかった時間(ミリ秒単位)。 | |
そのクラスターでのサブ検索のシャードの詳細。 | |
検索応答ボディには、_index パラメータにリモートクラスターの名前が含まれています。 |
複数のリモートクラスターを検索
次の検索APIリクエストは、3つのクラスターでmy-index-000001
インデックスを検索します:
- ローカル(「クエリ中」)クラスター、10シャード
- 2つのリモートクラスター、
cluster_one
、12シャードおよびcluster_two
、6シャード。
Python
resp = client.search(
index="my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001',
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
_source: [
'user.id',
'message',
'http.response.status_code'
]
}
)
puts response
Js
const response = await client.search({
index:
"my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
GET /my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001/_search
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
コンソール-結果
{
"took": 150,
"timed_out": false,
"num_reduce_phases": 4,
"_shards": {
"total": 28,
"successful": 28,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total": 3,
"successful": 3,
"skipped": 0,
"running": 0,
"partial": 0,
"failed": 0,
"details": {
"(local)": {
"status": "successful",
"indices": "my-index-000001",
"took": 21,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "successful",
"indices": "my-index-000001",
"took": 48,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"skipped": 0,
"failed": 0
}
},
"cluster_two": {
"status": "successful",
"indices": "my-index-000001",
"took": 141,
"timed_out": false,
"_shards": {
"total" : 6,
"successful" : 6,
"skipped": 0,
"failed": 0
}
}
}
},
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "my-index-000001",
"_id": "0",
"_score": 2,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
},
{
"_index": "cluster_one:my-index-000001",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
},
{
"_index": "cluster_two:my-index-000001",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
}
]
}
}
ローカル(クエリ中)クラスターは「(local)」として識別されます。 | |
このドキュメントの_index パラメータにはクラスター名が含まれていません。これは、ドキュメントがローカルクラスターから来たことを意味します。 |
|
このドキュメントはcluster_one から来ました。 |
|
このドキュメントはcluster_two から来ました。 |
ccs_minimize_roundtrips=trueを使用したクラスター間検索の非同期検索
リモートクラスターは、非同期検索APIを使用して非同期にクエリできます。クラスター間検索は、ccs_minimize_roundtrips
パラメータを受け入れます。非同期検索の場合、デフォルトはfalse
です。(注:同期検索の場合、デフォルトはtrue
です。)クラスター間検索でラウンドトリップを最小限に抑えるかどうかを選択する際の考慮事項を参照して、このオプションについて詳しく学んでください。
次のリクエストは、my-index-000001
インデックスをccs_minimize_roundtrips=true
を使用して3つのクラスター(前の例と同じ)に対して非同期検索を実行します。
Python
resp = client.async_search.submit(
index="my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
ccs_minimize_roundtrips=True,
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
Ruby
response = client.async_search.submit(
index: 'my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001',
ccs_minimize_roundtrips: true,
body: {
query: {
match: {
'user.id' => 'kimchy'
}
},
_source: [
'user.id',
'message',
'http.response.status_code'
]
}
)
puts response
Js
const response = await client.asyncSearch.submit({
index:
"my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
ccs_minimize_roundtrips: "true",
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
POST /my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001/_async_search?ccs_minimize_roundtrips=true
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
コンソール-結果
{
"id": "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
"is_partial": true,
"is_running": true,
"start_time_in_millis": 1685563581380,
"expiration_time_in_millis": 1685995581380,
"response": {
"took": 1020,
"timed_out": false,
"num_reduce_phases": 0,
"_shards": {
"total": 10,
"successful": 0,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total" : 3,
"successful" : 0,
"skipped": 0,
"running": 3,
"partial": 0,
"failed": 0,
"details": {
"(local)": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false
},
"cluster_one": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false
},
"cluster_one": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false
}
}
},
"hits": {
"total" : {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
}
}
非同期検索ID。 | |
ccs_minimize_roundtrips = true で、リモートクラスターでの検索がまだ実行中の場合、このセクションはローカルクラスターのみのスコープ内のシャード数を示し、検索が完了したクラスターの数も示します。検索が完了したときに、すべてのクラスターの合計シャード数が含まれるように更新されます。ccs_minimize_roundtrips = false の場合、すべてのクラスターの合計シャード数は事前に知られており、正確になります。 |
|
_clusters セクションは、検索のスコープ内に3つのクラスターがあり、すべてが現在「実行中」状態であることを示しています。 |
非同期検索を取得するエンドポイントをクエリ中に実行すると、各クラスターが検索を完了するたびに、応答の_clusters
および_shards
セクションに更新が表示されます。
`````ccs_minimize_roundtrips=true`````を設定すると、これまでに完了したすべてのクラスターからの「ヒット」および「集計」セクションの部分的な結果も表示されます。(注:ローカルクラスターからの部分的な集計結果も、完了する前に表示されることがあります。)以下の例は`````ccs_minimize_roundtrips=true`````のケースを示しています。
#### Python
``````python
resp = client.async_search.get(
id="FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
)
print(resp)
`
Ruby
response = client.async_search.get(
id: 'FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU='
)
puts response
Js
const response = await client.asyncSearch.get({
id: "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
});
console.log(response);
コンソール
GET /_async_search/FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=
コンソール-結果
{
"id": "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
"is_partial": true,
"is_running": true,
"start_time_in_millis": 1685564911108,
"expiration_time_in_millis": 1685996911108,
"response": {
"took": 11164,
"timed_out": false,
"terminated_early": false,
"_shards": {
"total": 22,
"successful": 22,
"skipped": 0,
"failed": 0
},
"_clusters": {
"total": 3,
"successful": 2,
"skipped": 0,
"running": 1,
"partial": 0,
"failed": 0,
"details": {
"(local)": {
"status": "successful",
"indices": "my-index-000001",
"took": 2034,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "successful",
"indices": "my-index-000001",
"took": 9039,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"skipped": 0,
"failed": 0
}
},
"cluster_two": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false
}
}
},
"hits": {
"total": {
"value": 542,
"relation": "eq"
},
"max_score": 1.7232,
"hits": [...list of hits here...]
}
}
}
ローカルクラスターとリモートcluster_one クラスターのすべてのシャードでの検索が完了しました。 |
|
2つのクラスターが検索を完了したため、「成功した」クラスターのエントリは2に設定され、「実行中」クラスターのエントリは1に減少します。_clusters 応答メタデータは、各クラスターが完了するにつれて更新されます。 |
|
完了した検索からのヒットの数。すべてのクラスターでの検索が完了し、マージされるまで、最終的なヒットは表示されません。したがって、「ヒット」セクションは、検索が完全に終了するまで、このエンドポイントを呼び出すと変更される可能性があります。 |
すべてのクラスターでの検索が完了した後、非同期検索を取得するエンドポイントをクエリすると、_clusters
および_shards
セクションの最終ステータスとヒット、集計結果が表示されます。
Python
resp = client.async_search.get(
id="FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
)
print(resp)
Ruby
response = client.async_search.get(
id: 'FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU='
)
puts response
Js
const response = await client.asyncSearch.get({
id: "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
});
console.log(response);
コンソール
GET /_async_search/FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=
コンソール-結果
{
"id": "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
"is_partial": false,
"is_running": false,
"start_time_in_millis": 1685564911108,
"expiration_time_in_millis": 1685996911108,
"completion_time_in_millis": 1685564938727,
"response": {
"took": 27619,
"timed_out": false,
"num_reduce_phases": 4,
"_shards": {
"total": 28,
"successful": 28,
"skipped": 0,
"failed": 0
},
"_clusters": {
"total": 3,
"successful": 3,
"skipped": 0,
"running": 0,
"partial": 0,
"failed": 0,
"details": {
"(local)": {
"status": "successful",
"indices": "my-index-000001",
"took": 2034,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "successful",
"indices": "my-index-000001",
"took": 9039,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"skipped": 0,
"failed": 0
}
},
"cluster_two": {
"status": "successful",
"indices": "my-index-000001",
"took": 27550,
"timed_out": false,
"_shards": {
"total": 6,
"successful": 6,
"skipped": 0,
"failed": 0
}
}
}
},
"hits": {
"total": {
"value": 1067,
"relation": "eq"
},
"max_score": 1.8293576,
"hits": [...list of hits here...]
}
}
}
検索が完了すると、completion_timeが表示されます。 | |
_shards セクションは、すべてのクラスターで検索された合計28シャードが成功したことを示すように更新されます。 |
|
_clusters セクションは、3つのクラスターでの検索が成功したことを示しています。 |
クラスター間検索の失敗
クラスター間検索中の失敗は、次の2つの条件のいずれかを引き起こす可能性があります:
- 1. 部分的な結果(2xx HTTPステータスコード)
- 2. 失敗した検索(4xxまたは5xx HTTPステータスコード)
失敗の詳細は、両方のケースで検索応答に表示されます。
個々のシャードでの検索の失敗は、応答の`````_shards`````セクションと`````_clusters`````セクションの両方に表示されます。
失敗した検索には、応答に追加のトップレベル`````errors`````エントリがあります。
以下は、1つのクラスターの1つのシャードの失敗による部分的な結果を持つ検索の例です。この検索は、以前に示されたものと似ています。`````_async_search/status`````エンドポイントは、完了ステータスを表示し、ヒットを表示しないために使用されます。
#### Python
``````python
resp = client.async_search.status(
id="FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw",
)
print(resp)
`
Ruby
response = client.async_search.status(
id: 'FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw'
)
puts response
Js
const response = await client.asyncSearch.status({
id: "FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw",
});
console.log(response);
コンソール
GET /_async_search/status/FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw
コンソール-結果
{
"id": "FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw",
"is_partial": true,
"is_running": false,
"start_time_in_millis": 1692106901478,
"expiration_time_in_millis": 1692538901478,
"completion_time_in_millis": 1692106903547,
"response": {
"took": 2069,
"timed_out": false,
"num_reduce_phases": 4,
"_shards": {
"total": 28,
"successful": 27,
"skipped": 0,
"failed": 1,
"failures": [
{
"shard": 1,
"index": "cluster_two:my-index-000001",
"node": "LMpUnAu0QEeCUMfg_56sAg",
"reason": {
"type": "query_shard_exception",
"reason": "failed to create query: [my-index-000001][1] exception message here",
"index_uuid": "4F2VWx8RQSeIhUE-nksvCQ",
"index": "cluster_two:my-index-000001",
"caused_by": {
"type": "runtime_exception",
"reason": "runtime_exception: [my-index-000001][1] exception message here"
}
}
}
]
},
"_clusters": {
"total": 3,
"successful": 2,
"skipped": 0,
"running": 0,
"partial": 1,
"failed": 0,
"details": {
"(local)": {
"status": "successful",
"indices": "my-index-000001",
"took": 1753,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "successful",
"indices": "my-index-000001",
"took": 2054,
"timed_out": false,
"_shards": {
"total": 12,
"successful": 12,
"skipped": 0,
"failed": 0
}
},
"cluster_two": {
"status": "partial",
"indices": "my-index-000001",
"took": 2039,
"timed_out": false,
"_shards": {
"total": 6,
"successful": 5,
"skipped": 0,
"failed": 1
},
"failures": [
{
"shard": 1,
"index": "cluster_two:my-index-000001",
"node": "LMpUnAu0QEeCUMfg_56sAg",
"reason": {
"type": "query_shard_exception",
"reason": "failed to create query: [my-index-000001][1] exception message here",
"index_uuid": "4F2VWx8RQSeIhUE-nksvCQ",
"index": "cluster_two:my-index-000001",
"caused_by": {
"type": "runtime_exception",
"reason": "runtime_exception: [my-index-000001][1] exception message here"
}
}
}
]
}
}
},
"hits": {
}
}
}
検索結果は部分的としてマークされます。少なくとも1つのシャード検索が失敗したためです。 | |
_shards セクションにはシャードの失敗情報が含まれています。 |
|
部分的な結果を持つクラスターは、依然として「部分的」としてマークされます。データが検索から返されなかった場合にのみ、ステータスは「スキップ」(または「失敗」)としてマークされます。 | |
partial ステータスは、部分的な結果を持つクラスターに適用されます。 |
|
失敗したシャードの数が表示されます。 | |
シャードの失敗は、クラスター/詳細エントリの下にもリストされます。 |
以下は、cluster_one
とcluster_two
の両方がクラスター間検索中に接続を失った例です。cluster_one
がskip_unavailable
=true
としてマークされているため、そのステータスはskipped
であり、cluster_two
がskip_unavailable
=false
としてマークされているため、そのステータスはfailed
です。failed
クラスターがあったため、トップレベルerror
も存在し、HTTPステータス500(表示されていません)を返します。
クラスターが利用できない場合でも検索が結果を返すようにするには、すべてのリモートクラスターに対してskip_unavailable
=true
を設定します。
Python
resp = client.async_search.get(
id="FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4",
)
print(resp)
Ruby
response = client.async_search.get(
id: 'FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4'
)
puts response
Js
const response = await client.asyncSearch.get({
id: "FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4",
});
console.log(response);
コンソール
GET /_async_search/FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4
コンソール-結果
{
"id": "FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4",
"is_partial": true,
"is_running": false,
"start_time_in_millis": 1692112102650,
"expiration_time_in_millis": 1692544102650,
"completion_time_in_millis": 1692112106177,
"response": {
"took": 3527,
"timed_out": false,
"terminated_early": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
},
"_clusters": {
"total": 3,
"successful": 1,
"skipped": 1,
"running": 0,
"partial": 0,
"failed": 1,
"details": {
"(local)": {
"status": "successful",
"indices": "my-index-000001",
"took": 1473,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 10,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "skipped",
"indices": "my-index-000001",
"timed_out": false,
"failures": [
{
"shard": -1,
"index": null,
"reason": {
"type": "node_disconnected_exception",
"reason": "[myhostname1][35.238.149.1:9300][indices:data/read/search] disconnected"
}
}
]
},
"cluster_two": {
"status": "failed",
"indices": "my-index-000001",
"timed_out": false,
"failures": [
{
"shard": -1,
"index": null,
"reason": {
"type": "node_disconnected_exception",
"reason": "[myhostname2][35.238.149.2:9300][indices:data/read/search] disconnected"
}
}
]
}
}
},
"hits": {
},
}
"error": {
"type": "status_exception",
"reason": "error while executing search",
"caused_by": {
"type": "node_disconnected_exception",
"reason": "[myhostname2][35.238.149.2:9300][indices:data/read/search] disconnected"
}
}
}
このようなエラーが発生した場合、シャードの会計はしばしば部分的なものになります。リモートクラスターからのシャード情報を各検索で取得できる必要があります。 | |
cluster_one が検索中に切断され、結果を返しませんでした。リモートクラスター構成でskip_unavailable =true としてマークされているため、そのステータスは「スキップ」であり、全体の検索を失敗させることはありません。 |
|
失敗リストには、リモートクラスターのノードがクエリ中のクラスターから切断されたことが示されています。 | |
cluster_two ステータスは「失敗」となります。リモートクラスター構成でskip_unavailable =false としてマークされているためです。 |
|
「失敗した」クラスターがある場合、トップレベルerror エントリが含まれます。 |
クラスター間検索からクラスターまたはインデックスを除外する
大規模なクラスターおよび/またはインデックスのリストを含めるためにワイルドカードを使用する場合、クラスターまたはインデックスの前に-
マイナス記号を付けて、1つ以上のクラスターまたはインデックスを明示的に除外できます。
クラスター全体を除外するには、クラスターエイリアスの前にマイナス記号を付けます。たとえば、-mycluster:*
のようにします。クラスターを除外する場合、インデックス位置に*
を使用する必要があります。さもなければエラーが返されます。
特定のリモートインデックスを除外するには、インデックスの前にマイナス記号を付けます。たとえば、mycluster:-myindex
のようにします。
リモートクラスターを除外する
ワイルドカードを使用してクラスターのリストを指定するクラスター間検索からcluster_three
を除外する方法は次のとおりです:
Python
resp = client.async_search.submit(
index="my-index-000001,cluster*:my-index-000001,-cluster_three:*",
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
Js
const response = await client.asyncSearch.submit({
index: "my-index-000001,cluster*:my-index-000001,-cluster_three:*",
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
POST /my-index-000001,cluster*:my-index-000001,-cluster_three:*/_async_search
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
cluster* 表記はcluster_one 、cluster_two 、cluster_three を自然に含むでしょう。 クラスター名の前に - を使用してcluster_three を除外し、インデックス位置にシンプルなワイルドカード* を使用します。これは、cluster_three との接触を望まないことを示します。 |
リモートインデックスを除外する
#### Python
``````python
resp = client.async_search.submit(
index="my-index-000001,cluster*:my-index-*,cluster_three:-my-index-000001",
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
`
Js
const response = await client.asyncSearch.submit({
index: "my-index-000001,cluster*:my-index-*,cluster_three:-my-index-000001",
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
POST /my-index-000001,cluster*:my-index-*,cluster_three:-my-index-000001/_async_search
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
これはcluster_three を検索から除外しません。my-index-* に一致するインデックスを検索するように依然として連絡されますが、my-index-000001 を除外します。 |
ccs_minimize_roundtrips=falseを使用したクラスター間検索の非同期検索
応答の_shards
および_clusters
セクションは、ccs_minimize_roundtrips
がfalse
の場合に異なる動作をします。
主な違いは:
- 1.
_shards
セクションの合計カウントは、検索が開始される前にすべてのクラスターからのシャードの合計数が収集されるため、すぐに正確になります。 - 2.
_shards
セクションは、個々のシャードの検索が完了するにつれて段階的に更新されますが、ラウンドトリップを最小限に抑える場合、シャードセクションはローカルクラスターでのシャードの検索が完了したときに更新され、その後、各リモートクラスターが完全な検索結果を報告するたびに更新されます。 - 3.
_cluster
セクションは、クエリフェーズが開始される前に取得されるため、すべてのシャードカウントをリストします。
前のセクション(ccs_minimize_roundtrips=true
)と同じセットアップを使用した例:
Python
resp = client.async_search.submit(
index="my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
ccs_minimize_roundtrips=False,
query={
"match": {
"user.id": "kimchy"
}
},
source=[
"user.id",
"message",
"http.response.status_code"
],
)
print(resp)
Js
const response = await client.asyncSearch.submit({
index:
"my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001",
ccs_minimize_roundtrips: "false",
query: {
match: {
"user.id": "kimchy",
},
},
_source: ["user.id", "message", "http.response.status_code"],
});
console.log(response);
コンソール
POST /my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001/_async_search?ccs_minimize_roundtrips=false
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
APIは、クエリがwait_for_completion_timeout
の期間を超えると、次の応答を返します(非同期検索を参照)。
コンソール-結果
{
"id": "FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU=",
"is_partial": true,
"is_running": true,
"start_time_in_millis": 1685563581380,
"expiration_time_in_millis": 1685995581380,
"response": {
"took": 1020,
"timed_out": false,
"_shards": {
"total": 28,
"successful": 0,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total" : 3,
"successful": 0,
"skipped": 0,
"running": 3,
"partial": 0,
"failed": 0,
"details": {
"(local)": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false,
"_shards": {
"total": 10,
"successful": 0,
"skipped": 0,
"failed": 0
}
},
"cluster_one": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false,
"_shards": {
"total": 12,
"successful": 0,
"skipped": 0,
"failed": 0
}
},
"cluster_two": {
"status": "running",
"indices": "my-index-000001",
"timed_out": false,
"_shards": {
"total": 6,
"successful": 0,
"skipped": 0,
"failed": 0
}
}
}
},
"hits": {
"total" : {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
}
}
検索のスコープ内のすべてのクラスターからのすべてのシャードがここにリストされています。このセクションや/または_clustersセクションを監視して、検索の進行状況を監視します。 | |
_clusters セクションから、すべてのクラスターが「実行中」状態であることがわかります。 |
|
_clusters セクションは、すべての3つのクラスターからシャード情報が正常に収集され、各クラスターの合計シャード数がリストされていることを示しています。 |
オプションのリモートクラスター
デフォルトでは、リクエスト内のリモートクラスターが利用できない場合、またはすべてのシャードでの検索が失敗した場合、クラスター間検索は失敗します。特定のリモートクラスターをオプションまたは必須としてマークするには、skip_unavailable
クラスター設定を使用します。
Elasticsearch 8.15では、skip_unavailable
のデフォルト値がfalse
からtrue
に変更されました。Elasticsearch 8.15以前は、クラスターをクラスター間検索のオプションとして扱うには、その構成を設定する必要がありました。Elasticsearch 8.15以降は、クラスターをクラスター間検索の必須とするには、その構成を設定する必要があります。
- 検索中にノードが利用できない場合、リモートクラスターをスキップします。応答の`````_clusters.skipped`````値には、スキップされたクラスターの数が含まれ、応答の`````_clusters.details`````セクションには`````skipped`````ステータスが表示されます。
- 利用できないシャードやインデックスに関連するエラーなど、リモートクラスターから返されたエラーを無視します。これには、[`````allow_no_indices`````](b10cb0563daae284.md#api-multi-index)や[`````ignore_unavailable`````](b10cb0563daae284.md#api-multi-index)などの検索パラメータに関連するエラーが含まれる場合があります。
- リモートクラスターを検索する際に、[`````allow_partial_search_results`````](89159571f146b334.md#search-partial-responses)パラメータと関連する`````search.default_allow_partial_results`````クラスター設定を無視します。これは、リモートクラスターでの検索が部分的な結果を返す可能性があることを意味します。
`````skip_unavailable`````設定は、elasticsearch.yml構成ファイルの`````cluster.remote.<cluster_alias>`````設定を編集することで変更できます。たとえば:
``````bash
cluster:
remote:
cluster_one:
seeds: 35.238.149.1:9300
skip_unavailable: false
cluster_two:
seeds: 35.238.149.2:9300
skip_unavailable: true
`
または、クラスター更新設定APIを介してクラスターのリモート設定を設定することもできます。
skip_unavailable: true
(上記のcluster_two
など)で構成されたリモートクラスターがクラスター間検索中に切断または利用できない場合、Elasticsearchはそのクラスターからの一致するドキュメントを最終結果に含めず、検索は成功と見なされます(HTTPステータス200 OK)。
クラスターの少なくとも1つのシャードが検索結果を提供する場合、それらの結果が使用され、検索は部分的なデータを返します。これは、リモートクラスターのskip_unavailable
設定に関係なく真です。(非同期検索を使用してクラスター間検索を行う場合、is_partial
フィールドは部分的な結果を示すためにtrue
に設定されます。)
クラスター間検索がネットワーク遅延を処理する方法
クラスター間検索はリモートクラスターにリクエストを送信するため、ネットワーク遅延が検索速度に影響を与える可能性があります。遅い検索を避けるために、クラスター間検索はネットワーク遅延を処理するための2つのオプションを提供します:
- ネットワークラウンドトリップを最小限に抑える
- デフォルトでは、Elasticsearchはリモートクラスター間のネットワークラウンドトリップの数を減らします。これにより、検索速度に対するネットワーク遅延の影響が軽減されます。ただし、Elasticsearchは、スクロールや内部ヒットを含む大規模な検索リクエストに対してネットワークラウンドトリップを減らすことはできません。
このオプションの動作については、クラスター間検索でラウンドトリップを最小限に抑えるかどうかを選択する際の考慮事項を参照してください。 - ネットワークラウンドトリップを最小限に抑えない
- スクロールや内部ヒットを含む検索リクエストの場合、Elasticsearchは各リモートクラスターに対して複数の送信および受信リクエストを送信します。このオプションは、
ccs_minimize_roundtrips
パラメータをfalse
に設定することによっても選択できます。通常は遅くなりますが、低遅延のネットワークではうまく機能する場合があります。
ネットワークラウンドトリップを最小限に抑えないの動作については、こちらを参照してください。
ベクトルタイル検索APIは常にネットワークラウンドトリップを最小限に抑え、ccs_minimize_roundtrips
パラメータを含みません。
近似kNN検索はネットワークラウンドトリップを最小限に抑えることをサポートしておらず、ccs_minimize_roundtrips
パラメータをfalse
に設定します。
クラスター間検索でラウンドトリップを最小限に抑えるかどうかを選択する際の考慮事項
ラウンドトリップを最小限に抑える利点:
- 1. 大量のシャードをクエリするクラスター間検索では、ラウンドトリップを最小限に抑えるオプションが通常はるかに優れたパフォーマンスを提供します。これは、検索されるクラスターが高いネットワーク遅延を持つ場合(例:遠隔地)に特に当てはまります。
- 2. 非同期クラスター間検索を行うと、
GET _async_search/<search_id>
エンドポイントは、他のクラスターでの検索がまだ実行中であっても、結果を報告したすべてのクラスターからのトップヒットと集計を提供します。言い換えれば、検索が進行するにつれて「増分」部分結果を提供します。ローカルクラスターが検索に含まれている場合、特別な処理が行われ、ローカルクラスターでの検索がまだ実行中である間に部分的な集計を表示できます(ただし、部分的なトップヒットは表示されません)。
非同期検索を使用してラウンドトリップを最小限に抑えない場合、検索がまだ実行中である間に、個々のシャードが完了するたびにクエリの集計の部分的な結果を取得できます(クラスター全体ではなく)。ただし、すべてのクラスターでの検索が完了するまで、トップヒットは表示されません。
デフォルトでは、同期検索はラウンドトリップを最小限に抑え、非同期検索はそうではありません。ccs_minimize_roundtrips
パラメータを使用してデフォルトをオーバーライドし、true
またはfalse
のいずれかに設定できます。これは、このドキュメントのいくつかの例で示されています。
ネットワークの往復回数を最小限に抑える
ネットワークの往復回数を最小限に抑えた場合のクロスクラスター検索の動作は次のとおりです。
- 1. クロスクラスター検索リクエストをローカルクラスターに送信します。そのクラスターのコーディネーショニングノードがリクエストを受信し、解析します。
- 2. コーディネーショニングノードは、ローカルクラスターを含む各クラスターに対して単一の検索リクエストを送信します。各クラスターは独立して検索リクエストを実行し、リクエストに自分のクラスター設定を適用します。
- 3. 各リモートクラスターは、検索結果をコーディネーショニングノードに返します。
- 4. 各クラスターから結果を収集した後、コーディネーショニングノードはクロスクラスター検索応答で最終結果を返します。
ネットワークの往復回数を最小限に抑えない
ネットワークの往復回数を最小限に抑えない場合のクロスクラスター検索の動作は次のとおりです。
- 1. クロスクラスター検索リクエストをローカルクラスターに送信します。そのクラスターのコーディネーショニングノードがリクエストを受信し、解析します。
- 2. コーディネーショニングノードは、各リモートクラスターに「検索シャード」トランスポートレイヤーリクエストを送信し、各クラスターのどのシャードを検索すべきかを判断するために「マッチ可能」検索を実行させます。
- 3. 各リモートクラスターは、コーディネーショニングノードに応答を返します。この応答には、クロスクラスター検索リクエストが実行されるインデックスとシャードに関する情報が含まれています。
- 4. コーディネーショニングノードは、各シャードに検索リクエストを送信します。自分のクラスター内のシャードも含まれます。各シャードは独立して検索リクエストを実行します。
ネットワークの往復回数が最小限に抑えられない場合、検索はすべてのデータがコーディネーショニングノードのクラスターにあるかのように実行されます。このため、action.search.shard_count.limit
、pre_filter_shard_size
、およびmax_concurrent_shard_requests
のような検索を制限するクラスター設定を更新することをお勧めします。これらの制限が低すぎると、検索が拒否される可能性があります。
- 5. 各シャードは、検索結果をコーディネーショニングノードに返します。
- 6. 各クラスターから結果を収集した後、コーディネーショニングノードはクロスクラスター検索応答で最終結果を返します。
サポートされているクロスクラスター検索構成
8.0以降、Elasticはローカルクラスターから次のようなリモートクラスターへの検索をサポートしています:
- 前のマイナーバージョン。
- 同じバージョン。
- 同じメジャーバージョン内の新しいマイナーバージョン。
Elasticは、メジャーバージョンの最後のマイナーバージョンを実行しているローカルクラスターから、次のメジャーバージョンの任意のマイナーバージョンを実行しているリモートクラスターへの検索もサポートしています。たとえば、ローカルの7.17クラスターは、任意のリモート8.xクラスターを検索できます。
リモートクラスターのバージョン | |||||||||||||||||||
ローカルクラスターのバージョン | 6.8 | 7.1–7.16 | 7.17 | 8.0 | 8.1 | 8.2 | 8.3 | 8.4 | 8.5 | 8.6 | 8.7 | 8.8 | 8.9 | 8.10 | 8.11 | 8.12 | 8.13 | 8.14 | 8.15 |
6.8 | |||||||||||||||||||
7.1–7.16 | |||||||||||||||||||
7.17 | |||||||||||||||||||
8.0 | |||||||||||||||||||
8.1 | |||||||||||||||||||
8.2 | |||||||||||||||||||
8.3 | |||||||||||||||||||
8.4 | |||||||||||||||||||
8.5 | |||||||||||||||||||
8.6 | |||||||||||||||||||
8.7 | |||||||||||||||||||
8.8 | |||||||||||||||||||
8.9 | |||||||||||||||||||
8.10 | |||||||||||||||||||
8.11 | |||||||||||||||||||
8.12 | |||||||||||||||||||
8.13 | |||||||||||||||||||
8.14 | |||||||||||||||||||
8.15 |
EQL検索APIでは、ローカルクラスターとリモートクラスターは、7.17.7(含む)以前または8.5.1(含む)以前のバージョンを使用している場合、同じElasticsearchバージョンを使用する必要があります。
たとえば、ローカルの8.0クラスターは、リモートの7.17または任意のリモート8.xクラスターを検索できます。ただし、ローカルの8.0クラスターからリモートの7.16または6.8クラスターへの検索はサポートされていません。
すべての検索されたクラスターに存在する機能のみがサポートされています。機能がサポートされていないリモートクラスターで機能を使用すると、未定義の動作が発生します。
サポートされていない構成を使用したクロスクラスター検索は、まだ機能する可能性があります。ただし、そのような検索はElasticによってテストされておらず、その動作は保証されていません。
クロスクラスター検索のサポートを確保する
クラスターがクロスクラスター検索をサポートしていることを確認する最も簡単な方法は、各クラスターを同じElasticsearchバージョンに保つことです。異なるバージョンのクラスターを維持する必要がある場合は、次のことができます:
- クロスクラスター検索専用のクラスターを維持します。このクラスターは、他のクラスターを検索するために必要な最も古いバージョンに保ちます。たとえば、7.17と8.xのクラスターがある場合、クロスクラスター検索のローカルクラスターとして使用するために専用の7.17クラスターを維持できます。
- 各クラスターを1つのマイナーバージョン以上離さないようにします。これにより、クロスクラスター検索を実行する際に任意のクラスターをローカルクラスターとして使用できます。
アップグレード中のクロスクラスター検索
ローカルクラスターでローリングアップグレードを実行している間でも、リモートクラスターを検索することができます。ただし、ローカルコーディネーティングノードの「アップグレード元」と「アップグレード先」バージョンは、リモートクラスターのゲートウェイノードと互換性がある必要があります。
アップグレードの期間を超えて同じクラスター内で複数のバージョンのElasticsearchを実行することはサポートされていません。
アップグレードに関する詳細については、Elasticsearchのアップグレードを参照してください。