搜索分片路由

为了确保冗余性并提高搜索性能,UDB-SX 将索引数据分布在多个主分片上,每个主分片有一个或多个副本分片。当执行搜索查询时,UDB-SX 会将请求路由到包含主分片或副本索引分片的节点。这种技术称为 搜索分片路由

自适应副本选择

为了改善延迟,搜索请求使用 自适应副本选择 进行路由,该算法基于以下因素选择节点:

  • 特定节点运行先前请求所花费的时间。

  • 协调节点与所选节点之间的延迟。

  • 节点搜索线程池的队列大小。

如果您有权调用 UDB-SX REST API,可以关闭搜索分片路由。有关 REST API 用户访问的更多信息,请参阅 REST 管理 API 设置。要禁用搜索分片路由,请更新集群设置如下:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.use_adaptive_replica_selection": false
  }
}

如果您关闭搜索分片路由,UDB-SX 将使用轮询路由,这可能会对搜索延迟产生负面影响。

搜索期间的节点和分片选择

UDB-SX 使用所有节点来选择搜索请求的最佳路由。但是,在某些情况下,您可能希望手动选择发送搜索请求的节点或分片,包括以下情况:

  • 使用缓存的先前搜索结果。

  • 为搜索分配特定的硬件。

  • 仅使用本地节点进行搜索。

您可以在搜索查询中使用 preference 参数来指定搜索目的地。以下是可用选项的完整列表:

  1. _primary:强制搜索仅在主分片上执行。

    GET /my-index/_search?preference=_primary
    
  2. _primary_first:优先使用主分片,但如果主分片不可用,将使用副本分片。

    GET /my-index/_search?preference=_primary_first
    
  3. _replica:强制搜索仅在副本分片上执行。

    GET /my-index/_search?preference=_replica
    
  4. _replica_first:优先使用副本分片,但如果副本分片不可用,将使用主分片。

    GET /my-index/_search?preference=_replica_first
    
  5. _only_nodes:<node-id>,<node-id>:将搜索限制为仅在具有指定 ID 的特定节点上执行。

    GET /my-index/_search?preference=_only_nodes:node-1,node-2
    
  6. _prefer_nodes:<node-id>,<node-id>:优先在特定节点上执行搜索,但如果首选节点不可用,将使用其他节点。

    GET /my-index/_search?preference=_prefer_nodes:node-1,node-2
    
  7. _shards:<shard-id>,<shard-id>:将搜索限制为特定分片。

    GET /my-index/_search?preference=_shards:0,1
    
  8. _local:尽可能在本地节点上执行搜索,这可以减少延迟。

    GET /my-index/_search?preference=_local
    
  9. 自定义字符串:您可以使用任何自定义字符串作为偏好值。此自定义字符串确保包含相同字符串的请求被一致地路由到相同的分片,这对于缓存很有用。

    GET /my-index/_search?preference=custom_string
    

索引和搜索期间的自定义路由

您可以在索引和搜索操作期间指定路由。

索引期间的路由

当您索引文档时,UDB-SX 会计算路由值的哈希值,并使用此哈希值来确定文档将存储在哪个分片上。如果您未指定路由值,UDB-SX 将使用文档 ID 来计算哈希值。

以下是带有路由值的索引操作示例:

POST /index1/_doc/1?routing=user1
{
  "name": "John Doe",
  "age": 20
}

在此示例中,ID 为 1 的文档使用路由值 user1 进行索引。所有具有相同路由值的文档将存储在同一分片上。

搜索期间的路由

当您搜索文档时,指定相同的路由值可确保搜索请求被路由到适当的分片。这可以通过减少需要查询的分片数量来显著提高性能。

以下示例请求使用特定路由值进行搜索:

GET /index1/_search?routing=user1
{
  "query": {
    "match": {
      "name": "John Doe"
    }
  }
}

在此示例中,搜索查询被路由到包含使用路由值 user1 索引的文档的分片。

使用自定义路由时需要注意,以防止热点和数据倾斜:

  • 热点 发生在不成比例的文档数量被路由到单个分片时。这可能导致该分片成为瓶颈,因为它必须处理比其他分片更多的读写操作。因此,该分片可能会经历更高的 CPU、内存和 I/O 使用率,导致性能下降。

  • 数据倾斜 指的是数据在分片之间分布不均匀。如果路由值分布不均,某些分片最终可能比其他分片存储更多的数据。这可能导致存储使用不平衡,其中某些节点的磁盘利用率远高于其他节点。

并发分片请求

在搜索期间同时命中大量分片会显著影响 CPU 和内存消耗。默认情况下,UDB-SX 不会拒绝这些请求。但是,有多种方法可以降低此风险。以下各节描述了这些方法。

限制可以并发查询的分片数量

您可以在搜索请求中使用 max_concurrent_shard_requests 参数来限制可以并发查询的分片数量。例如,以下请求将并发分片请求数限制为 12

GET /index1/_search?max_concurrent_shard_requests=12
{
  "query": {
    "match_all": {}
  }
}

定义搜索分片数量限制

您可以在 opensearch.yml 文件中或使用 REST API 定义动态设置 action.search.shard_count.limit。任何超过此限制的搜索请求都将被拒绝并抛出错误。这有助于防止单个搜索请求消耗过多资源,从而降低整个集群的性能。以下示例请求使用 API 更新此集群设置:

PUT /_cluster/settings
{
  "transient": {
    "action.search.shard_count.limit": 1000
  }
}

搜索线程池

UDB-SX 使用线程池来管理各种任务的执行,包括搜索操作。搜索线程池专门用于搜索请求。您可以通过将以下设置添加到 opensearch.yml 来调整搜索线程池的大小和队列容量:

thread_pool.search.size: 100
thread_pool.search.queue_size: 1000

线程池状态

以下三种状态描述线程池操作:

  • 线程分配:如果搜索线程池中有可用线程,则请求立即分配给一个线程并开始处理。

  • 排队:如果搜索线程池中的所有线程都忙,则请求被放入队列。

  • 拒绝:如果队列已满(例如,排队请求的数量达到队列大小限制),则其他传入的搜索请求将被拒绝,直到队列中有可用空间。

您可以通过运行以下请求来检查搜索线程池的当前配置:

GET /_cat/thread_pool/search?v&h=id,name,active,rejected,completed,size,queue_size