跨集群搜索

edit

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

支持的API

edit

以下API支持跨集群搜索:

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

先决条件

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

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

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

跨集群搜索示例

edit

远程集群设置

edit

以下集群更新设置 API 请求添加了三个远程集群:cluster_onecluster_twocluster_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,它使用默认值false。有关详细信息,请参阅可选的远程集群部分。

搜索单个远程集群

edit

在搜索请求中,您可以在远程集群上指定数据流和索引,格式为 :

以下搜索 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
              }
          }
        }
      }
    ]
  }
}

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

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

用户提供的索引表达式。如果你提供了一个通配符,例如 logs-*, 这一部分将显示带有通配符的值,而不是正在搜索的具体索引。

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

该集群上子搜索的分片详情。

搜索响应体中包含了远程集群的名称,位于_index参数中。

搜索多个远程集群

edit

以下搜索 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

使用异步搜索进行跨集群搜索,设置ccs_minimize_roundtrips=true

edit

可以使用异步搜索 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 时,所有集群中的总分片数量是预先知道的,并且将是正确的。

The _clusters section indicates that 3 clusters are in scope for the search and all are currently in the "running" state.

如果您在查询仍在运行时查询获取异步搜索端点,您将在响应的_clusters_shards部分看到更新,因为每个集群完成其搜索。

如果你设置ccs_minimize_roundtrips=false,那么你还将看到来自已完成的分片(来自任何集群)的部分聚合结果,但在搜索完成之前,“hits”部分不会显示任何结果。

如果你设置ccs_minimize_roundtrips=true,那么你将在响应的“hits”和“aggregations”部分看到所有已完成集群的部分结果。(注意:即使本地集群尚未完成,你也可以看到来自本地集群的部分聚合结果。)下面的示例展示了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 个分片,并且所有分片都成功。

The _clusters section shows that searches on all 3 clusters were successful.

跨集群搜索失败

edit

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

  1. 部分结果(2xx HTTP状态码)
  2. 搜索失败(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": {
    }
  }
}

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

The _shards 部分包括分片失败信息。

有部分结果的集群仍标记为“部分”。只有在搜索未返回任何数据时,它们才会被标记为“跳过”(或“失败”)。

已将partial状态应用于集群,并得到了部分结果。

失败的shard数量已显示。

分片故障也会列在集群/详细信息条目下。

这里有一个示例,其中 cluster_onecluster_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, 其状态为“已跳过”,这不会导致整个搜索失败。

失败列表显示远程集群节点已与查询集群断开连接。

cluster_two 状态为“失败”,因为它在远程集群配置中被标记为 skip_unavailable=false

当存在“失败”的集群时,会包含一个顶级的 error 条目。

从跨集群搜索中排除集群或索引

edit

如果您使用通配符来包含一个大型集群和/或索引列表,您可以使用-减号明确排除一个或多个集群或索引。

要排除整个集群,您可以在集群别名前加上减号,例如:-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

edit

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部分我们可以看到所有集群都处于“运行”状态。

The _clusters section shows that shard information was successfully gathered from all 3 clusters and the total shard count on each cluster is listed.

可选的远程集群

edit

默认情况下,如果请求中的远程集群不可用或在所有分片上搜索失败并返回错误,跨集群搜索将失败。使用skip_unavailable集群设置将特定远程集群标记为跨集群搜索的可选或必需。

在 Elasticsearch 8.15 中,skip_unavailable 的默认值从 false 更改为 true。在 Elasticsearch 8.15 之前,如果您希望将一个集群视为跨集群搜索的可选集群,则需要设置该配置。从 Elasticsearch 8.15 开始,您需要设置配置以使一个集群成为跨集群搜索的必需集群。

如果 skip_unavailabletrue,跨集群搜索:

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

您可以通过编辑 elasticsearch.yml 配置文件中的 cluster.remote. 设置来修改 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以指示部分结果。)

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

edit

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

Minimize network roundtrips

默认情况下,Elasticsearch减少了远程集群之间的网络往返次数。这减少了网络延迟对搜索速度的影响。然而,Elasticsearch无法减少大型搜索请求的网络往返次数,例如那些包括滚动内部命中的请求。

请参阅在跨集群搜索中选择是否最小化往返次数的考虑因素以了解此选项的工作原理。

Don’t minimize network roundtrips

对于包含滚动或内部命中的搜索请求,Elasticsearch会向每个远程集群发送多个出站和入站请求。您也可以通过将ccs_minimize_roundtrips参数设置为false来选择此选项。虽然通常较慢,但这种方法可能适用于低延迟的网络。

参见不要最小化网络往返以了解此选项的工作原理。

The vector tile search API 总是最小化网络往返次数,并且不包含 ccs_minimize_roundtrips 参数。

近似kNN搜索不支持最小化网络往返次数,并将参数ccs_minimize_roundtrips设置为false

选择是否在跨集群搜索中减少往返次数的考虑因素

edit

减少往返次数的优点:

  1. 对于查询大量分片的跨集群搜索,minimize roundtrips选项通常会提供更好的性能。如果被搜索的集群具有高网络延迟(例如,远地理区域),这一点尤其明显。
  2. 在进行异步跨集群搜索时,GET _async_search/端点将提供所有已返回结果的集群的顶部命中和聚合,即使在其他集群上搜索仍在进行时也是如此。换句话说,它会在搜索进行过程中提供“增量”的部分结果。请注意,如果本地集群包含在搜索中,它有特殊的处理方式,即在本地集群上的搜索仍在进行时,可以显示部分聚合(但不包括部分顶部命中)。

在使用异步搜索时不最小化往返次数,可以在搜索仍在进行时,随着单个分片完成(而不是整个集群),获取查询中任何聚合的增量结果,但在所有集群上的搜索完成之前,不会显示顶部命中。

默认情况下,同步搜索会减少往返次数,而异步搜索则不会。您可以通过使用ccs_minimize_roundtrips参数来覆盖默认设置,将其设置为truefalse,如本文档前面几个示例所示。

最小化网络往返次数

edit

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

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

    ccs 最小往返客户端请求

  2. 协调节点向每个集群发送一个搜索请求,包括本地集群。每个集群独立执行搜索请求,并应用其自身的集群级别设置到请求中。

    ccs 最小往返集群搜索

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

    ccs 最小往返集群结果

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

    ccs min roundtrip client response

不要最小化网络往返次数

edit

以下是不减少网络往返时跨集群搜索的工作原理。

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

    ccs min roundtrip client request

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

    ccs 最小往返集群搜索

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

    ccs 最小往返集群结果

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

    当网络往返未被最小化时,搜索将执行,就好像所有数据都在协调节点的集群中一样。我们建议更新集群级别的设置,以限制搜索,例如 action.search.shard_count.limitpre_filter_shard_sizemax_concurrent_shard_requests,以适应这种情况。如果这些限制设置得太低,搜索可能会被拒绝。

    ccs 不要最小化往返分片搜索

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

    ccs 不要最小化往返分片结果

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

    ccs 最小往返客户端响应

支持的跨集群搜索配置

edit

在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 search API,如果本地和远程集群的版本在7.17.7(包括)之前或8.5.1(包括)之前,它们必须使用相同的Elasticsearch版本。

例如,本地 8.0 集群可以搜索远程 7.17 或任何远程 8.x 集群。然而,从本地 8.0 集群到远程 7.16 或 6.8 集群的搜索是不支持的。

仅支持在所有搜索的集群中都存在的功能。如果在不支持该功能的远程集群中使用该功能,将导致未定义的行为。

使用不支持配置的跨集群搜索可能仍然有效。然而,此类搜索未经过Elastic的测试,其行为不保证。

确保跨集群搜索支持

edit

确保您的集群支持跨集群搜索的最简单方法是保持每个集群在同一版本的Elasticsearch上。如果您需要维护不同版本的集群,您可以:

  • 维护一个专用的跨集群搜索集群。将此集群保持在所需搜索其他集群的最早版本。例如,如果您有7.17和8.x集群,您可以维护一个专用的7.17集群,用作跨集群搜索的本地集群。
  • 保持每个集群之间的次要版本不超过一个。这使您可以在运行跨集群搜索时将任何集群用作本地集群。

升级期间的跨集群搜索

edit

在本地集群进行滚动升级时,您仍然可以搜索远程集群。然而,本地协调节点的“升级自”和“升级至”版本必须与远程集群的网关节点兼容。

在同一集群中运行多个版本的Elasticsearch超过升级期间是不支持的。

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