索引分片分配

edit

此模块提供每个索引的设置,以控制分片分配到节点:

索引级分片分配过滤

edit

您可以使用分片分配过滤器来控制 Elasticsearch 在何处分配特定索引的分片。这些每个索引的过滤器与集群范围的分配过滤分配感知一起应用。

分片分配过滤器可以根据自定义节点属性或内置的 _name, _host_ip, _publish_ip, _ip, _host, _id, _tier_tier_preference 属性进行。索引生命周期管理使用基于自定义节点属性的过滤器来确定在不同阶段之间移动时如何重新分配分片。

The cluster.routing.allocation 设置是动态的,允许现有索引立即从一个节点集移动到另一个节点集。只有在不违反其他路由约束(例如,永远不会在同一节点上分配主分片和副本分片)的情况下,分片才会被重新定位。

例如,您可以使用自定义节点属性来指示节点的性能特征,并使用分片分配过滤来将特定索引的分片路由到最合适的硬件类别。

启用索引级分片分配过滤

edit

根据自定义节点属性进行过滤:

  1. 在每个节点的 elasticsearch.yml 配置文件中使用自定义节点属性来指定过滤特性。例如,如果你有 smallmediumbig 节点,你可以添加一个 size 属性来根据节点大小进行过滤。

    node.attr.size: medium

    您也可以在启动节点时设置自定义属性:

    ./bin/elasticsearch -Enode.attr.size=medium
  2. 向索引添加路由分配过滤器。index.routing.allocation设置支持三种类型的过滤器:includeexcluderequire。例如,要告诉Elasticsearch将test索引的分片分配给bigmedium节点,请使用index.routing.allocation.include

    PUT test/_settings
    {
      "index.routing.allocation.include.size": "big,medium"
    }

    如果你指定了多个过滤器,以下条件必须同时被一个节点满足,以便分片能够被重新定位到该节点:

    • 如果指定了任何 require 类型的条件,所有这些条件都必须被满足
    • 如果指定了任何 exclude 类型的条件,这些条件都不能被满足
    • 如果指定了任何 include 类型的条件,至少其中一个条件必须被满足

    例如,要将 test 索引移动到 rack1 中的 big 节点,您可以指定:

    PUT test/_settings
    {
      "index.routing.allocation.require.size": "big",
      "index.routing.allocation.require.rack": "rack1"
    }

索引分配过滤设置

edit
index.routing.allocation.include.{attribute}
将索引分配给一个节点,该节点的 {attribute} 具有逗号分隔值中的至少一个。
index.routing.allocation.require.{attribute}
将索引分配给一个节点,该节点的 {attribute} 具有 所有 逗号分隔的值。
index.routing.allocation.exclude.{attribute}
将索引分配给一个节点,该节点的 {attribute} 不包含逗号分隔值中的任何一个。

索引分配设置支持以下内置属性:

_name

通过节点名称匹配节点

_host_ip

根据主机IP地址匹配节点(与主机名关联的IP)

_publish_ip

通过发布IP地址匹配节点

_ip

匹配 _host_ip_publish_ip

_host

通过主机名匹配节点

_id

通过节点ID匹配节点

_tier

根据节点的数据层角色匹配节点。 有关更多详细信息,请参阅数据层分配过滤

_tier 过滤是基于 节点 角色的。只有一部分角色是 数据层 角色,而通用的 数据角色 将匹配任何层过滤。

在指定属性值时,您可以使用通配符,例如:

PUT test/_settings
{
  "index.routing.allocation.include._ip": "192.168.2.*"
}

节点离开时的延迟分配

edit

当一个节点无论出于何种原因(有意或无意)离开集群时,主节点会做出如下反应:

  • 将副本分片提升为主分片,以替换节点上的任何主分片。
  • 分配副本分片以替换丢失的副本(假设有足够的节点)。
  • 在剩余节点之间均匀地重新平衡分片。

这些操作旨在通过确保每个分片尽快完全复制来保护集群免受数据丢失的影响。

尽管我们在节点级别集群级别都对并发恢复进行了限制,但这种“分片重排”仍然可能给集群带来大量额外的负载,如果丢失的节点很可能很快返回,这种负载可能是不必要的。想象一下这个场景:

  • 节点5失去网络连接。
  • 主节点将每个位于节点5上的主分片的副本分片提升为主分片。
  • 主节点将新的副本分配到集群中的其他节点。
  • 每个新的副本通过网络复制主分片的完整副本。
  • 更多的分片被移动到不同的节点以重新平衡集群。
  • 节点5在几分钟后恢复。
  • 主节点通过将分片分配到节点5来重新平衡集群。

如果主节点只等待几分钟,那么丢失的分片就可以被重新分配到节点5,并且网络流量最小。对于空闲分片(不接收索引请求的分片),这个过程会更快,因为它们已经被自动刷新

由于节点离开而变为未分配的副本分片的分配可以被延迟,使用动态设置index.unassigned.node_left.delayed_timeout,其默认值为1m

此设置可以在实时索引上更新(或在所有索引上更新):

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "5m"
  }
}

启用延迟分配后,上述场景将变为如下所示:

  • 节点5失去网络连接。
  • 主节点将每个位于节点5的主分片的一个副本分片提升为主分片。
  • 主节点记录一条消息,说明未分配分片的分配已被延迟,以及延迟的时间。
  • 集群保持黄色状态,因为存在未分配的副本分片。
  • 节点5在超时到期之前几分钟返回。
  • 缺失的副本被重新分配到节点5(并且同步刷新的分片几乎立即恢复)。

此设置不会影响副本提升为主节点,也不会影响之前未分配的副本的分配。特别是,延迟分配在集群完全重启后不会生效。此外,在主节点故障转移的情况下,已过去的延迟时间会被遗忘(即重置为完整的初始延迟)。

分片重定位的取消

edit

如果延迟分配超时,主节点会将缺失的分片分配给另一个节点,该节点将开始恢复。如果缺失的节点重新加入集群,并且其分片仍然具有与主节点相同的同步ID,则分片重新定位将被取消,并且同步的分片将用于恢复。

因此,默认的 timeout 设置为一分钟:即使分片重新定位开始,取消恢复以支持同步分片也是廉价的。

监控延迟未分配的分片

edit

由于此超时设置而延迟分配的分片数量可以通过集群健康API查看:

GET _cluster/health 

此请求将返回一个 delayed_unassigned_shards 值。

永久删除节点

edit

如果一个节点不会返回,并且您希望 Elasticsearch 立即分配丢失的分片,只需将超时时间更新为零:

PUT _all/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": "0"
  }
}

一旦丢失的分片开始恢复,您可以重置超时时间。

索引恢复优先级

edit

未分配的分片会尽可能按照优先级顺序进行恢复。 索引按照以下优先级顺序进行排序:

  • 可选的 index.priority 设置(高优先级在前)
  • 索引创建日期(新创建的在前)
  • 索引名称(按字母顺序排列,高优先级在前)

这意味着,默认情况下,较新的索引将比旧索引优先恢复。

使用每个索引的动态可更新设置 index.priority 来自定义索引优先级顺序。例如:

PUT index_1

PUT index_2

PUT index_3
{
  "settings": {
    "index.priority": 10
  }
}

PUT index_4
{
  "settings": {
    "index.priority": 5
  }
}

在上面的例子中:

  • index_3 将首先恢复,因为它具有最高的 index.priority
  • index_4 将接下来恢复,因为它具有次高的优先级。
  • index_2 将接下来恢复,因为它创建得更近。
  • index_1 将最后恢复。

此设置接受一个整数,并且可以使用更新索引设置 API在实时索引上进行更新:

PUT index_4/_settings
{
  "index.priority": 1
}

每个节点的总分片数

edit

集群级别的分片分配器试图将单个索引的分片分散到尽可能多的节点上。然而,根据您拥有的分片和索引数量,以及它们的大小,可能并不总是能够均匀地分散分片。

以下动态设置允许您为每个节点上来自单个索引的分片总数指定一个硬性限制:

index.routing.allocation.total_shards_per_node
单个节点上将分配的最大分片数(副本和主分片)。默认为无限制。

您也可以限制节点可以拥有的分片数量,无论索引如何:

cluster.routing.allocation.total_shards_per_node

(动态) 每个节点分配的主分片和副本分片的数量上限。默认为 -1(无限制)。

Elasticsearch 在分片分配期间检查此设置。例如,一个集群有一个 cluster.routing.allocation.total_shards_per_node 设置为 100,并且有三个节点,其分片分配如下:

  • 节点 A: 100 个分片
  • 节点 B: 98 个分片
  • 节点 C: 1 个分片

如果节点 C 失败,Elasticsearch 会将它的分片重新分配到节点 B。将分片重新分配到节点 A 会超过节点 A 的分片限制。

这些设置施加了硬性限制,可能导致某些分片未被分配。

请谨慎使用。

索引级别数据层分配过滤

edit

您可以使用索引级别的 _tier_preference 设置来控制索引分配到哪个 数据层

此设置对应于数据节点角色:

The 数据节点角色不是一个有效的数据层,不能与_tier_preference设置一起使用。冻结层专门存储部分挂载的索引

数据层分配设置

edit
index.routing.allocation.include._tier_preference
将索引分配给列表中第一个有可用节点的层级。 这可以防止在首选层级中没有可用节点时,索引保持未分配状态。 例如,如果您将 index.routing.allocation.include._tier_preference 设置为 data_warm,data_hot,如果存在具有 data_warm 角色的节点,则索引将分配给温层。如果温层中没有节点, 但存在具有 data_hot 角色的节点,则索引将分配给热层。 与 数据层级 一起使用。