跨集群搜索编辑

跨集群搜索 允许您对一个或多个远程集群运行单个搜索请求。例如,您可以使用跨集群搜索来过滤和分析存储在不同数据中心集群上的日志数据。

支持的 API编辑

以下 API 支持跨集群搜索

  • 搜索
  • 异步搜索
  • 多重搜索
  • 搜索模板
  • 多重搜索模板
  • 字段功能
  • Painless 执行 API
  • 解析索引 API
  • [预览] 此功能处于技术预览阶段,可能会在未来版本中更改或删除。Elastic 将努力修复任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。 EQL 搜索
  • [预览] 此功能处于技术预览阶段,可能会在未来版本中更改或删除。Elastic 将努力修复任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。 SQL 搜索
  • [预览] 此功能处于技术预览阶段,可能会在未来版本中更改或删除。Elastic 将努力修复任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。 矢量切片搜索
  • [预览] 此功能处于技术预览阶段,可能会在未来版本中更改或删除。Elastic 将努力修复任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。 ES|QL

先决条件编辑

  • 如果您使用 嗅探模式,则本地协调节点必须能够连接到远程集群上的种子节点和网关节点。

    我们建议使用能够充当协调节点的网关节点。种子节点可以是这些网关节点的子集。

  • 如果您使用 代理模式,则本地协调节点必须能够连接到已配置的 proxy_address。此地址处的代理必须能够将连接路由到远程集群上的网关节点和协调节点。
  • 跨集群搜索需要在本地集群和远程集群上具有不同的安全权限。请参阅 为跨集群搜索配置权限远程集群

跨集群搜索示例编辑

远程集群设置编辑

以下 集群更新设置 API 请求添加了三个远程集群:cluster_onecluster_twocluster_three

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
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,因此它使用默认值 false。有关详细信息,请参阅 可选的远程集群 部分。

搜索单个远程集群编辑

在搜索请求中,您将远程集群上的数据流和索引指定为 <remote_cluster_name>:<target>

以下 搜索 API 请求搜索单个远程集群 cluster_one 上的 my-index-000001 索引。

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
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
              }
          }
        }
      }
    ]
  }
}

计数器的这一部分显示了所有可能的集群搜索状态以及当前处于该状态的集群搜索数量。集群可以处于以下状态之一:正在运行成功(所有分片上的搜索均成功)、部分(集群中至少一个分片上的搜索成功,至少一个失败)、已跳过(搜索在标记为 skip_unavailable=true 的集群上失败)或 失败(搜索在标记为 skip_unavailable=false 的集群上失败)。

_clusters/details 部分显示了每个集群上搜索的元数据。

用户提供的索引表达式。如果您提供通配符(例如 logs-*),则此部分将显示带有通配符的值,而不是正在搜索的具体索引。

子搜索在该集群上花费的时间(以毫秒为单位)。

该集群上子搜索的分片详细信息。

搜索响应正文在 _index 参数中包含远程集群的名称。

搜索多个远程集群编辑

以下 搜索 API 请求在三个集群上搜索 my-index-000001 索引

  • 本地(查询)集群,具有 10 个分片
  • 两个远程集群,cluster_one 具有 12 个分片,cluster_two 具有 6 个分片。
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
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
              }
          }
        }
      }
    ]
  }
}

本地(查询)集群标识为“(本地)”。

此文档的 _index 参数不包含集群名称。这意味着该文档来自本地集群。

此文档来自 cluster_one

此文档来自 cluster_two

使用异步搜索进行跨集群搜索,其中 ccs_minimize_roundtrips=true编辑

可以使用 异步搜索 API 异步查询远程集群。跨集群搜索接受 ccs_minimize_roundtrips 参数。对于异步搜索,它默认为 false。(注意:对于同步搜索,它默认为 true。)请参阅 选择是否在跨集群搜索中最小化往返次数的注意事项 以详细了解此选项。

以下请求使用 ccs_minimize_roundtrips=true 对三个集群(与上一个示例相同)对 my-index-000001 索引进行异步搜索。

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
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,则您还将看到已完成的分片(来自任何集群)的部分聚合结果,但在搜索完成之前,“hits”部分不会显示任何结果。

如果设置 ccs_minimize_roundtrips=true,则您还将在响应的“hits”和“aggregations”部分中看到来自迄今为止已完成的所有集群的部分结果。(注意:即使在本地集群完成之前,您也可以看到来自本地集群的部分聚合结果。)下面的示例显示了 ccs_minimize_roundtrips=true 的情况。

response = client.async_search.get(
  id: 'FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU='
)
puts 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 集群的所有分片上的搜索已完成。

由于两个集群已完成搜索,因此“successful”集群条目设置为 2,“running”集群条目减少为 1。 _clusters 响应元数据将在每个集群完成时更新。

到目前为止,已完成搜索的命中次数。在所有集群上的搜索完成并合并之前,不会显示最终命中次数。因此,在搜索完全完成之前,“hits”部分可能会随着您调用此端点而发生变化。

在所有集群上的搜索完成后,查询 获取异步搜索 端点将显示 _clusters_shards 部分的最终状态,以及命中次数和任何聚合结果。

response = client.async_search.get(
  id: 'FklQYndoTDJ2VEFlMEVBTzFJMGhJVFEaLVlKYndBWWZSMUdicUc4WVlEaFl4ZzoxNTU='
)
puts 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 个集群上的搜索均已成功。

跨集群搜索失败编辑

跨集群搜索期间的失败可能导致以下两种情况之一

  1. 部分结果(2xx HTTP 状态代码)
  2. 搜索失败(4xx 或 5xx HTTP 状态代码)

在这两种情况下,搜索响应中都会显示失败详细信息。

如果标记为 skip_unavailable=false 的集群不可用、在搜索期间断开连接或所有分片上的搜索均失败,则搜索将失败。在所有其他情况下,失败将导致部分结果。

单个分片上的搜索失败将显示在响应的 _shards 部分和 _clusters 部分中。

搜索失败将在响应中包含一个额外的顶级 errors 条目。

下面是一个搜索示例,由于一个集群的一个分片出现故障,导致搜索结果不完整。搜索将类似于前面显示的搜索。此处使用 _async_search/status 端点来显示完成状态,而不显示命中次数。

response = client.async_search.status(
  id: 'FmpwbThueVB4UkRDeUxqb1l4akIza3cbWEJyeVBPQldTV3FGZGdIeUVabXBldzoyMDIw'
)
puts 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": {
    }
  }
}

搜索结果标记为部分结果,因为至少有一个分片搜索失败。

_shards 部分包含分片失败信息。

具有部分结果的集群仍标记为“partial”。仅当搜索未返回任何数据时,它们才会标记为状态“skipped”(或“failed”)。

“partial”状态已应用于具有部分结果的集群。

显示了失败的分片数。

分片故障也列在 cluster/details 条目下。

下面是一个示例,其中 cluster_onecluster_two 在跨集群搜索期间失去连接。由于 cluster_one 标记为 skip_unavailable=true,因此其状态为“skipped”,而由于 cluster_two 标记为 skip_unavailable=false,因此其状态为“failed”。由于存在“failed”集群,因此还会出现顶级 error,并且这将返回 500 的 HTTP 状态(未显示)。

如果希望即使某个集群不可用,搜索仍能返回结果,请为所有远程集群设置 skip_unavailable=true

response = client.async_search.get(
  id: 'FjktRGJ1Y2w1U0phLTRhZnVyeUZ2MVEbWEJyeVBPQldTV3FGZGdIeUVabXBldzo5NzA4'
)
puts 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,因此其状态为“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  
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "_source": ["user.id", "message", "http.response.status_code"]
}

cluster* 表示法自然会包含 cluster_onecluster_twocluster_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  
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "_source": ["user.id", "message", "http.response.status_code"]
}

不会从搜索中排除 cluster_three。它仍然会被联系并被告知搜索与 my-index-* 匹配的任何索引,但 my-index-000001 除外。

将异步搜索用于 ccs_minimize_roundtrips=false 的跨集群搜索编辑

ccs_minimize_roundtripsfalse 时,响应的 _shards_clusters 部分的行为会有所不同。

主要区别在于

  1. _shards 部分的总数将立即准确,因为在搜索开始之前,会从所有集群收集分片的总数。
  2. 随着单个分片上的搜索完成,_shards 部分将逐步更新,而在最小化往返次数时,随着本地集群上的分片搜索完成以及每个远程集群报告其完整搜索结果,将更新分片部分。
  3. _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 集群设置将特定的远程集群标记为跨集群搜索的可选集群。

如果 skip_unavailabletrue,则跨集群搜索将

  • 如果远程集群的节点在搜索期间不可用,则跳过该集群。响应的 _clusters.skipped 值包含任何已跳过集群的计数,响应的 _clusters.details 部分将显示 skipped 状态。
  • 忽略远程集群返回的错误,例如与不可用分片或索引相关的错误。这可以包括与搜索参数相关的错误,例如 allow_no_indicesignore_unavailable
  • 在搜索远程集群时,忽略 allow_partial_search_results 参数和相关的 search.default_allow_partial_results 集群设置。这意味着对远程集群的搜索可能会返回部分结果。

以下 集群更新设置 API 请求将 cluster_twoskip_unavailable 设置更改为 true

PUT _cluster/settings
{
  "persistent": {
    "cluster.remote.cluster_two.skip_unavailable": true
  }
}

如果 cluster_two 在跨集群搜索期间断开连接或不可用,则 Elasticsearch 不会在最终结果中包含来自该集群的匹配文档。如果至少有一个分片提供结果,则将使用这些结果,并且搜索将返回部分数据。(如果使用异步搜索执行跨集群搜索,则 is_partial 字段将设置为 true 以指示部分结果。)

跨集群搜索如何处理网络延迟编辑

由于跨集群搜索涉及向远程集群发送请求,因此任何网络延迟都会影响搜索速度。为了避免搜索速度慢,跨集群搜索提供了两种处理网络延迟的选项

最小化网络往返次数

默认情况下,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 参数覆盖默认值,将其设置为 truefalse,如本文档前面的几个示例所示。

最小化网络往返次数编辑

以下是当您最小化网络往返次数时跨集群搜索的工作原理。

  1. 您向本地集群发送跨集群搜索请求。该集群中的协调节点接收并解析请求。

    ccs min roundtrip client request

  2. 协调节点向每个集群(包括本地集群)发送单个搜索请求。每个集群独立执行搜索请求,将自己的集群级设置应用于请求。

    ccs min roundtrip cluster search

  3. 每个远程集群将其搜索结果发送回协调节点。

    ccs min roundtrip cluster results

  4. 从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。

    ccs min roundtrip client response

不要最小化网络往返次数编辑

以下是当您不最小化网络往返次数时跨集群搜索的工作原理。

  1. 您向本地集群发送跨集群搜索请求。该集群中的协调节点接收并解析请求。

    ccs min roundtrip client request

  2. 协调节点向每个远程集群发送“搜索分片”传输层请求,让他们执行“可以匹配”搜索,以确定应搜索每个集群上的哪些分片。

    ccs min roundtrip cluster search

  3. 每个远程集群将其响应发送回协调节点。此响应包含有关将执行跨集群搜索请求的索引和分片的信息。

    ccs min roundtrip cluster results

  4. 协调节点向每个分片(包括其自身集群中的分片)发送搜索请求。每个分片独立执行搜索请求。

    当网络往返次数没有最小化时,搜索的执行就好像所有数据都在协调节点的集群中一样。我们建议更新限制搜索的集群级设置,例如 action.search.shard_count.limitpre_filter_shard_sizemax_concurrent_shard_requests,以解决此问题。如果这些限制太低,则搜索可能会被拒绝。

    ccs dont min roundtrip shard search

  5. 每个分片将其搜索结果发送回协调节点。

    ccs dont min roundtrip shard results

  6. 从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。

    ccs min roundtrip client response

支持的跨集群搜索配置编辑

在 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

6.8

Yes

Yes

Yes

No

No

No

No

No

No

No

No

No

No

No

No

No

No

No

7.1–7.16

Yes

Yes

Yes

No

No

No

No

No

No

No

No

No

No

No

No

No

No

No

7.17

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.0

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.1

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.2

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.3

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.4

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.5

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.6

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.7

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.8

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.9

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

8.10

No

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

8.11

No

No

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

8.12

No

No

No

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

Yes

8.13

No

No

No

No

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

Yes

8.14

No

No

No

No

No

No

No

No

No

No

No

No

No

No

No

No

Yes

Yes

对于 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 集群,用作跨集群搜索的本地集群。
  • 将每个集群之间的版本差异保持在一个次要版本以内。这使您可以在运行跨集群搜索时使用任何集群作为本地集群。

升级期间的跨集群搜索编辑

在对本地集群执行滚动升级时,您仍然可以搜索远程集群。但是,本地协调节点的“升级来源”和“升级目标”版本必须与远程集群的网关节点兼容。

不支持在升级持续时间之外在同一个集群中运行多个版本的 Elasticsearch。

有关升级的更多信息,请参阅 升级 Elasticsearch