elasticsearch分片分配控制

elasticsearch分片分配控制

分片片分配是指将索引分片分配到其他节点的过程,如下情况都会执行索引分片的分配。

  • 集群故障恢复
  • 副本分配
  • 索引动态均衡(节点增加或者减少后自动进行)
  • 索引新建

集群级路由

主服务器的主要作用之一是确定将哪些分片分配给哪些节点,以及何时在节点之间移动分片以重新平衡群集。

分片设置

  • cluster.routing.allocation.enable:启用或禁用特定种类的分片的分配
    • all - (默认)允许为所有类型的分片分配分片。
    • primaries - 仅允许主分片的分片分配。
    • new_primaries - 仅允许为新索引的主分片分配分片。
    • none - 任何索引都不允许任何类型的分片。

重新启动节点时,此设置不会影响本地节点主分片的恢复。具有未分配主分片副本的重新启动的节点将立即恢复该主节点,假设其分配标识符与集群状态中的一个活动分配标识匹配。

  • cluster.routing.allocation.node_concurrent_incoming_recoveries:允许在节点上发生多少并发的传入分片恢复。传入恢复是在节点上分配目标分片(很可能是副本,除非分片正在重定位)的恢复。默认为2。

  • cluster.routing.allocation.node_concurrent_outgoing_recoveries:节点上允许发生多少并发的传出分片恢复。传出恢复是在节点上分配源分片(除非分片重定位,很可能是主分片)的恢复。默认为2。

  • cluster.routing.allocation.node_concurrent_recoveries: 设置 cluster.routing.allocation.node_concurrent_incoming_recoveries 和 cluster.routing.allocation.node_concurrent_outgoing_recoveries 的快捷方式。

  • cluster.routing.allocation.node_initial_primaries_recoveries: 副本的恢复是通过网络的,但重新启动节点后未分配的主节点的恢复是使用本地磁盘中的数据。这些操作是快速的,所以初始主分片恢复可以在同一个节点上并行发生。默认并发度4 。

  • cluster.routing.allocation.same_shard.host: 允许执行检查以防止在单个主机上根据主机名和主机地址分配同一分片的多个实例。默认为 false ,这意味着默认情况下不执行检查。此设置仅适用于在同一台机器上启动多个节点的情况。

分片再平衡路由

  • cluster.routing.rebalance.enable: 为特定类型的分片启用或禁用平衡:

    • all -(默认)允许所有类型的分片进行分片平衡。
    • primaries -仅允许对主要分片进行分片平衡。
    • replicas -仅允许副本分片进行分片平衡。
    • none -任何索引都不允许任何形式的分片平衡。
  • cluster.routing.allocation.allow_rebalance:指定何时允许分片重新平衡:

    • always -始终允许重新平衡。
    • indices_primaries_active -仅在分配了集群中的所有主节点时。
    • indices_all_active -(默认)仅在分配了集群中的所有分片(主和副本)时。
  • cluster.routing.allocation.cluster_concurrent_rebalance:允许控制在群集范围内允许多少并发的分片重新平衡。默认为2。

分片平衡参数

  • cluster.routing.allocation.balance.shard:定义分配在该节点的分片数的因子,阈值=因子*(当前节点的分片数-集群的总分片数/节点数,即每个节点的平均分片数)
  • cluster.routing.allocation.balance.index: 定义分配在该节点某个索引的分片数的因子,阈值=因子*(保存当前节点的某个索引的分片数-索引的总分片数/节点数,即每个节点某个索引的平均分片数)
  • cluster.routing.allocation.balance.threshold:超出这个阈值就会重新分配分片,默认为1.0f

基于磁盘空间的分片分配

Elasticsearch在决定是向该节点分配新的分片还是主动从该节点重新分配分片之前,先考虑节点上的可用磁盘空间。

  • cluster.routing.allocation.disk.threshold_enabled:是否开启基于硬盘的分配策略,默认true
  • cluster.routing.allocation.disk.watermark.low:不会分配分片到硬盘使用率高于这个值的节点。默认值为85%
  • cluster.routing.allocation.disk.watermark.high:如果硬盘使用率高于这个值,则会重新分配该节点的分片到别的节点,默认为90%。
  • cluster.routing.allocation.disk.watermark.flood_stage:如果磁盘空间使用率高于这个值,该节点的分片的索引将会被设置成只读(index.blocks.read_only_allow_delete:true)。当使用率低于high水位时,该只读锁会被释放。默认值为95%。
  • cluster.info.update.interval:当前硬盘使用率的查询频率,默认为30s。
  • cluster.routing.allocation.disk.include_relocations:计算硬盘使用率时,是否加上正在重新分配给其他节点的分片的大小,默认为true。

注意,这些配置可以是百分比,也可以是具体大小,但是建议使用同一种风格。

分片感知控制

我们可以使用自定义节点属性作为感知属性,以使Elasticsearch在分配分片时考虑您的物理硬件配置。如果Elasticsearch知道哪些节点位于同一物理服务器上,位于同一机架中,或位于同一区域中,则它可以分发主分片及其副本分片,以最大程度地降低在发生故障时丢失所有分片副本的风险。

使用cluster.routing.allocation.awareness.attributes设置启用分片分配感知时 ,分片仅分配给具有指定的感知属性的值的节点。如果使用多个感知属性,Elasticsearch会在分配分片时单独考虑每个属性。Elasticsearch更喜欢在同一位置(具有相同的感知属性值)使用分片来处理搜索或GET请求。使用本地分片通常比跨越机架或区域边界更快。

通过下面的步骤启用分片分配感知:

  • 使用自定义节点属性指定每个节点的位置。例如,如果您希望Elasticsearch在不同机架上分发分片,您可以在每个节点的elasticsearch.yml 配置文件中设置rack_id为感知属性。
1
node.attr.rack_id: rack_one
  • 通过cluster.routing.allocation.awareness.attributes的值,告诉Elasticsearch在分配分片时考虑一个或多个感知属性。
1
2
# 多个属性指定以逗号分隔
cluster.routing.allocation.awareness.attributes: rack_id

使用上面示例配置,如果启动两个节点并且node.attr.rack_id设置为rack_one,然后创建包含5个主分片和和1个副本的索引,则会在两个节点之间分配所有主要分片和副本。如果添加两个node.attr.rack_id设置为的节点rack_two,Elasticsearch会将分片移动到新节点,确保(如果可能)同一个分片中没有两个副本位于同一个机架中。如果标识为rack_two的两个节点异常并断线,默认情况下Elasticsearch会将丢失的分片副本分配给其中的节点rack_one。要防止在同一位置分配特定分片的多个副本,可以启用强制感知。

强制感知

默认情况下,如果一个位置失败,Elasticsearch会将所有丢失的副本分片分配给其余位置。虽然您可能在所有位置拥有足够的资源来托管主分片和副本分片,但为防止单个位置在发生故障时过载,您可以设置cluster.routing.allocation.awareness.force,在没有其他位置的可用节点之前不分配任何副本。

举例来说,如果你有一个名为感知属性zone和属性值zone1和zone2,则可以使用强制感知防止Elasticsearch在一个zone上分配所有分片。

1
2
cluster.routing.allocation.awareness.attributes: zone
cluster.routing.allocation.awareness.force.zone.values: zone1,zone2

使用上面示例配置,如果启动两个节点并qienode.attr.zone设置为zone1并创建包含5个分片和1个副本的索引,Elasticsearch将创建索引并分配5个主分片但不分配副本。只有在node.attr.zone设置为zone2的节点可用时才会分配副本。

集群分片分配过滤器

可以使用群集级分片过滤器来控制索引分配分片的位置。分配过滤器可根据自定义节点的属性或内置 _name,_ip以及_host属性实现控制。cluster.routing.allocation设置是动态的,可以将实时索引从一组节点移动到另一组节点。

群集级分片过滤的最常见用例是要停用节点时。要在关闭节点之前将节点移出节点,可以创建一个按其IP地址排除节点的过滤器:

1
2
3
4
5
6
7
8
9
10
11
12
13
PUT _cluster/settings
{
"transient" : {
"cluster.routing.allocation.exclude._ip" : "10.0.0.1"
}
}
# 属性值可以为通配
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.exclude._ip": "192.168.2.*"
}
}
  • cluster.routing.allocation.include.{attribute}: "a,b,c": 将分片分配给attribute属性至少具有设置值之一的节点。
  • cluster.routing.allocation.require.{attribute}: "a,b,c": 仅将分片分配给attribute属性完全为设置值的节点
  • cluster.routing.allocation.exclude.{attribute}: "a,b,c": 不要将分片分配给attribute属性具有设置值中任一值的节点

集群默认支持以下内置属性:

  • _name: 按节点名称匹配节点
  • _ip:按IP地址匹配节点(与主机名关联的IP地址)
  • _host:按主机名匹配节点

其他分片相关配置

  • cluster.blocks.read_only: 将整个群集设为只读(索引不接受写操作),不允许修改元数据(创建或删除索引)。
  • cluster.blocks.read_only_allow_delete:与cluster.blocks.read_only索引相同,但允许删除索引以释放资源。
  • cluster.max_shards_per_node:默认为每个数据节点1000个分片,close掉的索引不计入其中。

索引级路由

索引级分片分配过滤器

索引级分片分配过滤器可根据自定义节点的属性或内置 _name,host_ip,publish_ip,_ip,和_host属性,来控制Elasticsearch在何处分配特定索引的分片。

基于自定义节点属性的过滤和集群分片感知中的属性配置步骤一致。

  • index.routing.allocation.include.{attribute}: "a,b,c": 将分片分配给attribute属性至少具有设置值之一的节点。
  • index.routing.allocation.require.{attribute}: "a,b,c": 仅将分片分配给attribute属性完全为设置值的节点
  • index.routing.allocation.exclude.{attribute}: "a,b,c":不要将分片分配给attribute属性具有设置值中任一值的节点

索引分配设置支持以下内置属性,指定属性值时,可以使用通配符:

  • _name:通过节点名称匹配节点
  • _host_ip: 通过主机IP地址(与主机名关联的IP)匹配节点
  • _publish_ip:通过发布IP地址匹配节点
  • _ip:匹配_host_ip或_publish_ip
  • _host:通过主机名匹配节点

节点离开时延迟分配

当节点出于任何原因离开群集时,主服务器会做出以下反应:

  • 将其他节点副本分片提升为主节点,以替换离开节点上的所有主节点。
  • 分配副本分片以替换丢失的副本(假设有足够的节点)。
  • 在其余节点之间平均分配碎片。

这些操作是为了尽快完全复制每个分片来保护群集,免受数据丢失风险。这会给群集增加很多额外的负载,如果丢失的节点可能很快就会返回,则可能没有必要这么做。下面是个例子:

  • 节点5失去网络连接。
  • 主节点将节点5上每个主节点的副本分片提升为主分片。
  • 主服务器将新副本分配给群集中的其他节点。
  • 每个新副本都会在网络上制作主分片片的完整副本。
  • 更多分片将移至不同节点以重新平衡群集。
  • 几分钟后,节点5返回。
  • 主服务器通过向节点5分配分片来重新平衡群集。

可以通过index.unassigned.node_left.delayed_timeout设置延迟时间,来暂缓由于节点离开而开始的副本分片分配,默认延时为1m。

  • 节点5失去网络连接。
  • 主节点将节点5上每个主节点的副本分片提升为的主分片。
  • 主服务器记录一条消息,指出未分配的副本分片的分配已延迟,并且延迟了多长时间。
  • 群集保持黄色,因为存在未分配的副本分片。
  • 几分钟后,节点5会在timeout到期之前返回。
  • 未分配的副本将重新分配给节点5(同步刷新的碎片几乎立即恢复)。

此设置将不会影响将副本升级为主副本,也不会影响之前未分配的副本的分配。特别是,在整个群集重新启动后,延迟分配不会生效。在发生master节点故障切换的情况下,未分配的副本分片的分配延迟时间会被忘记,重置为完整的初始延迟。

如果延迟分配超时,则主服务器将丢失的副本分片分配给另一个节点,并将开始恢复副本。如果丢失的节点重新加入群集,并且其分片仍具有与主节点相同的sync-id,则将取消分片重定位,并将同步的分片用于恢复。

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

1
2
3
4
5
6
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "0"
}
}

GET _cluster/health的返回值中的delayed_unassigned_shards表示当前集群延迟分配的分片数。

节点的shard数限制

集群级分片分配器尝试将单个索引的分片分布在尽可能多的节点上。但是,取决于拥有的分片和索引的数量以及它们的大小,可能并不总是能够均匀地分布分片。

  • index.routing.allocation.total_shards_per_node:将分配给单个节点的最大分片(副本和主副本)数量。默认为无界
  • cluster.routing.allocation.total_shards_per_node:全局设置,将分配给单个节点的最大分片(副本和主副本)数量。默认为无界

参考资料:

  • Shard allocation and cluster-level routing
  • Index Shard Allocation
-------------本文结束感谢您的阅读-------------
坚持分享,您的支持将鼓励我继续创作!
0%