跨集群搜索
Elastic Stack Serverless
通过跨集群搜索,您可以针对一个或多个远程集群运行单个搜索请求。 例如,您可以使用跨集群搜索来过滤和分析存储在不同数据中心的集群上的日志数据。
以下 API 支持跨集群搜索
- 搜索
- 异步搜索
- 多重搜索
- 搜索模板
- 多重搜索模板
- 字段能力
- Painless 执行 API
- 解析索引 API
- [预览] EQL 搜索
- [预览] SQL 搜索
- [预览] 矢量切片搜索
- [预览] ES|QL
跨集群搜索需要远程集群。 要设置远程集群,请参阅远程集群。
为确保您的远程集群配置支持跨集群搜索,请参阅支持的跨集群搜索配置。
为了获得完整的跨集群搜索功能,本地和远程集群必须位于相同的订阅级别上。
本地协调节点必须具有`remote_cluster_client`节点角色。
如果您使用嗅探模式,则本地协调节点必须能够连接到远程集群上的种子节点和网关节点。
我们建议使用能够充当协调节点的网关节点。 种子节点可以是这些网关节点的子集。
如果您使用代理模式,则本地协调节点必须能够连接到配置的 `proxy_address`。 此地址上的代理必须能够将连接路由到远程集群上的网关和协调节点。
跨集群搜索需要本地集群和远程集群上不同的安全权限。 请参阅配置跨集群搜索的权限和远程集群。
以下集群更新设置 API 请求添加了三个远程集群:`cluster_one`、`cluster_two` 和 `cluster_three`。
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"
]
}
}
}
}
}
- 由于没有在 `cluster_three` 上设置 `skip_unavailable`,因此它使用默认值 `true`。 有关详细信息,请参见可选远程集群部分。
在搜索请求中,您可以将远程集群上的数据流和索引指定为 `<remote_cluster_name>:<target>`。
以下搜索 API 请求搜索单个远程集群 `cluster_one` 上的 `my-index-000001` 索引。
GET /cluster_one:my-index-000001/_search
{
"size": 1,
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
API 返回以下响应。 请注意,当您搜索一个或多个远程集群时,将包含一个 `_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
}
}
}
}
]
}
}
- 计数器的此部分显示了所有可能的集群搜索状态以及当前处于该状态的集群搜索数量。 集群可以是以下状态之一:**running**、**successful**(所有分片上的搜索均成功)、**partial**(集群的至少一个分片上的搜索成功并且至少一个分片失败)、**skipped**(在标记为 `skip_unavailable`= `true` 的集群上搜索失败)或 **failed**(在标记为 `skip_unavailable`= `false` 的集群上搜索失败)。
- `_clusters/details` 部分显示了有关每个集群上搜索的元数据。
- 用户提供的索引表达式。 如果您提供诸如 `logs-*` 之类的通配符,则此部分将显示带有通配符的值,而不是正在搜索的具体索引。
- 子搜索在该集群上花费的时间(以毫秒为单位)。
- 该集群上子搜索的分片详细信息。
- 搜索响应正文在 `_index` 参数中包含远程集群的名称。
以下搜索 API 请求搜索三个集群上的 `my-index-000001` 索引
- 本地(查询)集群,具有 10 个分片
- 两个远程集群,`cluster_one`,具有 12 个分片,以及 `cluster_two` 具有 6 个分片。
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"]
}
API 返回以下响应
{
"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`。
可以使用异步搜索 API 异步查询远程集群。 跨集群搜索接受一个 `ccs_minimize_roundtrips` 参数。 对于异步搜索,它默认为 `false`。 (注意:对于同步搜索,它默认为 `true`。)有关此选项的更多信息,请参见选择是否最小化跨集群搜索中的往返次数的注意事项。
以下请求使用 `ccs_minimize_roundtrips=true` 对三个集群(与上一个示例相同)的 `my-index-000001` 索引进行异步搜索。
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"]
}
API 返回以下响应
{
"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=false`,那么您还会看到来自已完成分片(来自任何集群)的部分聚合结果,但是在搜索完成之前,不会在“命中”部分中显示任何结果。
如果您设置 `ccs_minimize_roundtrips=true`,那么您还会从迄今为止已完成的所有集群的响应的“命中”和“聚合”部分中看到部分结果。 (注意:即使在本地集群完成之前,您也可以看到来自本地集群的部分聚合结果。)以下示例显示了 `ccs_minimize_roundtrips=true` 的情况。
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` 集群的所有分片上的搜索均已完成。
- 由于两个集群已完成搜索,“successful”集群条目设置为 2,而“running”集群条目减少为 1。 `_clusters` 响应元数据将在每个集群完成时更新。
- 迄今为止已完成的搜索的命中数。 在完成并合并所有集群上的搜索之前,不会显示最终命中。 因此,在搜索完全完成之前,当您调用此端点时,“hits”部分可能会更改。
在所有集群上的搜索都完成后,查询 获取异步搜索端点将显示 `_clusters` 和 `_shards` 部分以及命中数和任何聚合结果的最终状态。
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 个集群上的搜索均已成功。
跨集群搜索期间的失败可能会导致以下两种情况之一
- 部分结果(2xx HTTP 状态代码)
- 搜索失败(4xx 或 5xx HTTP 状态代码)
在这两种情况下,失败详细信息都将出现在搜索响应中。
如果标记为 skip_unavailable
=false
的集群不可用、在搜索期间断开连接或所有分片上的搜索都失败,则搜索将会失败。在所有其他情况下,失败将导致部分结果。
单个分片上的搜索失败将显示在响应的 _shards
部分和 _clusters
部分中。
失败的搜索将在响应中包含一个额外的顶级 errors
条目。
这是一个由于一个集群的一个分片发生故障而导致部分结果的搜索示例。该搜索类似于之前显示的搜索。这里使用 _async_search/status
端点来显示完成状态,而不显示匹配项。
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": {
}
}
}
- 由于至少有一个分片搜索失败,因此搜索结果被标记为 partial(部分)。
_shards
部分包含分片失败信息。- 具有部分结果的集群仍然被标记为 "partial"。只有当搜索没有返回任何数据时,它们才会被标记为 "skipped"(跳过)或 "failed"(失败)状态。
partial
状态已应用于具有部分结果的集群。- 显示了失败的分片计数。
- 分片失败也列在 cluster/details 条目下。
这是一个示例,其中 cluster_one
和 cluster_two
在跨集群搜索期间都失去了连接。由于 cluster_one
被标记为 skip_unavailable
=true
,因此其状态为 skipped
,而由于 cluster_two
被标记为 skip_unavailable
=false
,因此其状态为 failed
。由于存在 failed
的集群,因此也会出现一个顶级 error
,并且这将返回 HTTP 状态 500(未显示)。
如果您希望即使在集群不可用时搜索仍然返回结果,请为所有远程集群设置 skip_unavailable
=true
。
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
,因此其状态为 "skipped",这不会导致整个搜索失败。- 失败列表显示远程集群节点与查询集群断开连接。
cluster_two
的状态为 "failed",因为它在远程集群配置中被标记为skip_unavailable
=false
。- 当存在 "failed" 集群时,将包含一个顶级
error
条目。
如果您使用通配符来包含大量的集群和/或索引列表,则可以使用集群或索引前面的 -
减号显式排除一个或多个集群或索引。
要排除整个集群,您需要在集群别名前面加上减号,例如:-mycluster:*
。排除集群时,您必须在索引位置使用 *
,否则将返回错误。
要排除特定的远程索引,您需要在索引前面加上减号,例如 mycluster:-myindex
。
排除远程集群
以下是如何从使用通配符指定集群列表的跨集群搜索中排除 cluster_three
POST /my-index-000001,cluster*:my-index-000001,-cluster_three:*/_async_search <1>
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
cluster*
表示法自然会包含cluster_one
、cluster_two
和cluster_three
。要排除cluster_three
,请在集群名称前使用-
以及索引位置中的简单通配符*
。这表明您不希望搜索与cluster_three
进行任何联系。
排除远程索引
假设您要搜索所有与 my-index-*
匹配的索引,但要排除 cluster_three
上的 my-index-000001
。以下是如何执行此操作
POST /my-index-000001,cluster*:my-index-*,cluster_three:-my-index-000001/_async_search <1>
{
"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
部分的行为不同。
主要区别是
_shards
部分的总计数将立即准确,因为分片总数是在搜索开始之前从所有集群收集的。_shards
部分将随着单个分片上的搜索完成而递增更新,而当最小化往返行程时,分片部分将随着本地集群上的分片搜索完成而更新,然后随着每个远程集群报告其完整搜索结果而更新。_cluster
部分首先列出其所有分片计数,因为它们也是在查询阶段开始之前获得的。
使用与上一节(ccs_minimize_roundtrips=true
)中相同的设置的示例
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"]
}
如果查询花费的时间超过 wait_for_completion_timeout
持续时间,则 API 返回以下响应(请参阅异步搜索)。
{
"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
部分,我们可以看到所有集群都处于 "running" 状态。 _clusters
部分显示已成功从所有 3 个集群收集了分片信息,并且列出了每个集群上的分片总数。
默认情况下,如果请求中的远程集群不可用或返回搜索所有分片都失败的错误,则跨集群搜索将失败。使用 skip_unavailable
集群设置来将特定的远程集群标记为跨集群搜索的可选或必需。
在 Elasticsearch 8.15 中,skip_unavailable
的默认值已从 false
更改为 true
。在 Elasticsearch 8.15 之前,如果您希望将集群视为跨集群搜索的可选集群,则需要设置该配置。从 Elasticsearch 8.15 开始,您需要设置配置才能使集群成为跨集群搜索的必需集群。
如果 skip_unavailable
为 true
,则跨集群搜索
- 如果远程集群的节点在搜索期间不可用,则跳过该远程集群。响应的
_clusters.skipped
值包含任何跳过的集群的计数,并且响应的_clusters.details
部分将显示skipped
状态。 - 忽略远程集群返回的错误,例如与不可用分片或索引相关的错误。这可以包括与搜索参数相关的错误,例如
allow_no_indices
和ignore_unavailable
。 - 忽略
allow_partial_search_results
参数以及搜索远程集群时相关的search.default_allow_partial_results
集群设置。这意味着远程集群上的搜索可能会返回部分结果。
您可以通过编辑 elasticsearch.yml
配置文件中的 cluster.remote.<cluster_alias>
设置来修改 skip_unavailable
设置。例如
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 设置 cluster.remote
设置,如此处所示。
当配置为 skip_unavailable: true
的远程集群(例如上面的 cluster_two
)在跨集群搜索期间断开连接或不可用时,Elasticsearch 不会将来自该集群的匹配文档包含在最终结果中,并且该搜索将被视为成功(HTTP 状态 200 OK)。
如果集群中的至少一个分片提供搜索结果,则将使用这些结果,并且搜索将返回部分数据。无论远程集群的 skip_unavailable
设置如何,都是如此。(如果使用异步搜索进行跨集群搜索,则 is_partial
字段将设置为 true
以指示部分结果。)
由于跨集群搜索涉及向远程集群发送请求,因此任何网络延迟都可能影响搜索速度。为了避免搜索速度慢,跨集群搜索提供了两种处理网络延迟的选项
- 最小化网络往返次数
-
默认情况下,Elasticsearch 减少了远程集群之间的网络往返次数。这降低了网络延迟对搜索速度的影响。但是,Elasticsearch 无法减少大型搜索请求的网络往返次数,例如包含 scroll 或 inner hits 的请求。
请参阅 选择是否在跨集群搜索中最小化往返行程的注意事项,以了解此选项的工作原理。
- 不最小化网络往返次数
-
对于包含 scroll 或 inner hits 的搜索请求,Elasticsearch 会向每个远程集群发送多个传出和传入的请求。您还可以通过将
ccs_minimize_roundtrips
参数设置为false
来选择此选项。虽然通常较慢,但此方法可能适用于具有低延迟的网络。请参阅 不要最小化网络往返行程,以了解此选项的工作原理。
矢量瓦片搜索 API 始终最小化网络往返行程,并且不包含 ccs_minimize_roundtrips
参数。
近似 kNN 搜索 不支持最小化网络往返行程,并将参数 ccs_minimize_roundtrips
设置为 false
。
最小化往返行程的优势
- 对于查询大量分片的跨集群搜索,最小化往返行程选项通常提供更好的性能。如果被搜索的集群具有较高的网络延迟(例如,遥远的地理区域),则尤其如此。
- 在执行异步跨集群搜索时,即使搜索仍在其他集群上运行,
GET _async_search/<search_id>
端点也会提供来自所有已报告返回结果的集群的点击数和聚合。换句话说,它会在搜索进行时提供“增量”部分结果。请注意,如果本地集群包含在搜索中,则它具有特殊的处理方式,因为它可以在本地集群上的搜索仍在运行时显示部分聚合(但不能显示部分点击数)。
在使用异步搜索时不最小化往返行程,允许您在搜索仍在运行时,作为单个分片完成(而不是整个集群)时,获得查询中任何聚合的增量结果,但在所有集群上完成搜索之前,不会显示点击数。
默认情况下,同步搜索会最小化往返行程,而异步搜索则不会。您可以覆盖默认值,方法是使用 ccs_minimize_roundtrips
参数,将其设置为 true
或 false
,如本文档前面的一些示例所示。
以下是最小化网络往返行程时跨集群搜索的工作方式。
您将跨集群搜索请求发送到本地集群。该集群中的协调节点接收并解析该请求。
协调节点向每个集群(包括本地集群)发送单个搜索请求。每个集群独立执行搜索请求,并将自己的集群级别设置应用于该请求。
每个远程集群将其搜索结果发送回协调节点。
在从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。
以下是不最小化网络往返行程时跨集群搜索的工作方式。
您将跨集群搜索请求发送到本地集群。该集群中的协调节点接收并解析该请求。
协调节点向每个远程集群发送“搜索分片”传输层请求,以使它们执行“can match”搜索,以确定应该搜索每个集群上的哪些分片。
每个远程集群将其响应发送回协调节点。此响应包含有关跨集群搜索请求将在哪些索引和分片上执行的信息。
协调节点向每个分片发送搜索请求,包括其自身集群中的分片。每个分片独立执行搜索请求。
警告当网络往返次数未最小化时,搜索的执行方式就像所有数据都在协调节点的集群中一样。我们建议更新限制搜索的集群级别设置,例如
action.search.shard_count.limit
、pre_filter_shard_size
和max_concurrent_shard_requests
,以解决此问题。如果这些限制太低,则搜索可能会被拒绝。每个分片将其搜索结果发送回协调节点。
在从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。
在 8.0+ 版本中,Elastic 支持从本地集群搜索到运行以下版本的远程集群:
- 之前的次要版本。
- 相同的版本。
- 同一主要版本中较新的次要版本。
Elastic 还支持从运行主要版本的最后一个次要版本的本地集群搜索到运行以下主要版本中任何次要版本的远程集群。例如,本地 8.18 集群可以搜索任何远程 9.x 集群。
远程集群版本 | ||||
本地集群版本 | 7.17 | 8.0 – 8.17 | 8.18 | 9.0 |
7.17 | ![]() |
![]() |
![]() |
![]() |
8.0 – 8.17 | ![]() |
![]() |
![]() |
![]() |
8.18 | ![]() |
![]() |
![]() |
![]() |
9.0 | ![]() |
![]() |
![]() |
![]() |
对于 EQL 搜索 API,如果本地和远程集群的版本早于 7.17.7(包含)或早于 8.5.1(包含),则它们必须使用相同的 Elasticsearch 版本。
例如,本地 9.0 集群可以搜索远程 8.18 或任何远程 9.x 集群。但是,不支持从本地 9.0 集群搜索到远程 8.17 或 7.17 集群。
仅支持所有搜索集群都存在的特性。在不支持该特性的远程集群中使用特性将导致未定义的行为。
使用不受支持的配置的跨集群搜索仍然可以工作。但是,Elastic 不会测试此类搜索,并且不保证其行为。
确保集群支持跨集群搜索的最简单方法是使每个集群都使用相同版本的 Elasticsearch。如果您需要维护不同版本的集群,您可以
- 维护一个专用于跨集群搜索的集群。使此集群保持在搜索其他集群所需的最早版本上。例如,如果您有 8.18 和 9.x 集群,则可以维护一个专用的 8.18 集群,将其用作跨集群搜索的本地集群。
- 保持每个集群之间的版本差异不超过一个次要版本。这样您就可以在运行跨集群搜索时将任何集群用作本地集群。
您仍然可以在本地集群上执行滚动升级时搜索远程集群。但是,本地协调节点的“升级自”和“升级到”版本必须与远程集群的网关节点兼容。
不支持在同一集群中运行多个版本的 Elasticsearch,超出升级的持续时间。
有关升级的更多信息,请参见 升级 Elasticsearch。