Elasticsearch分片平衡

Elasticsearch分片平衡

下面我们来介绍一些重要的概念:

  • 集群(cluster):代表一个集群,其中包含多个节点。集群中有一个主节点,这个主节点通过选举产生。主节点和从节点是集群内部的概念。Elasticsearch采用去中心化的设计,即在集群外部看来,没有中心节点,因为对外部来说,与任何一个节点通信和与整个Elasticsearch集群通信是等价的
  • 主分片(Primary Shard):代表索引的主分片。Elasticsearch可以将一个完整的索引分成多个主分片,将其分布在不同的节点上,实现分布式搜索。主分片的数量只能在索引创建前指定,并且创建后不能更改
  • 副本分片(Replica Shard):代表索引的副本分片。Elasticsearch可以为一个索引设置多个副本,副本的作用有两个方面:一是提高系统的容错性,当某个节点的分片损坏或丢失时,可以从副本中恢复数据;二是提高查询效率,Elasticsearch会自动对搜索请求进行负载均衡
  • 数据恢复(recovery):或重新分布是指在节点加入或退出集群时,根据机器的负载情况重新分配索引分片的过程。当一个节点重新启动时,也会进行数据恢复

什么情况下可能导致分片分布不均匀呢

  • 索引的动态均衡 :包括集群内部节点数量调整、新增索引、删除索引副本、删除索引等情况
  • 增加副本 :因有大量的数据集中写入到某个节点
  • 节点宕机:通常在下线一个Elasticsearch节点后,该节点上的主分片会被判定为丢失,此时Elasticsearch集群会自动将其他节点上的副本分片设置为主分片。当该节点重新启动时,分片数据会被识别为副本分片。这些操作可能导致一些节点上的主分片较为集中,而另一些节点上的副本分片较为集中
  • 大量集中数据写入:大量数据的集中写入可能导致主分片在短时间内不均匀的情况。当业务场景需要大量写入时,如果设置了较多的ingest节点进行写入,由于无法实时同步,可能会导致主分片在节点之间不均匀地分布

分片平衡影响范围

  1. 资源消耗
    • CPU 负载:重新平衡操作可能会消耗一定量的 CPU 资源,特别是在大规模集群或需要移动大量 shard 的情况下
    • 网络带宽:重新平衡过程中,节点之间需要传输 shard 数据,这可能会占用集群内部的网络带宽资源
  2. 延迟和响应时间
    1. 请求延迟:由于节点在重新平衡时可能忙于处理 shard 数据的迁移,因此可能会导致部分请求的响应时间增加
    2. 集群状态变化:在重新平衡期间,集群的状态可能会变化,例如某些 shard 的分配状态可能会在迁移过程中变为不可用或正在迁移
  3. 性能优化
    1. 平衡集群负载:良好的重新平衡策略可以帮助优化集群性能,确保各节点的负载均衡,从而提高整体的处理能力
    2. 故障转移:重新平衡还有助于在节点故障或新增节点时自动将 shard 迁移到健康的节点上,保证数据的可用性和复原能力
  4. 管理和配置
    1. 手动干预:有时需要手动干预来调整自动重新平衡策略,例如调整数据分片的分配策略,或者暂时禁用自动平衡以减少对生产环境的影响
    2. 监控和警报:监控集群的重新平衡过程是管理集群健康的重要部分,可以通过监控工具设置警报以便及时响应任何问题

集群shard分配策略

集群分片分配是指将索引的shard分配到其他节点的过程,会在如下情况下触发:

  • 集群内有节点宕机,需要故障恢复;
  • 增加副本;
  • 索引的动态均衡,包括集群内部节点数量调整、删除索引副本、删除索引等情况;

上述策略开关,可以动态调整,由参数cluster.routing.allocation.enable控制,启用或者禁用特定分片的分配。该参数的可选参数有

  • all - 默认值,允许为所有类型分片分配分片
  • primaries - 仅允许分配主分片的分片
  • new_primaries - 仅允许为新索引的主分片分配分片
  • none - 任何索引都不允许任何类型的分片

该设置不影响重启节点时本地主分片的恢复。如果一个重新启动的节点拥有一个未分配的主分片的副本,假设它的分配id与集群状态中的一个活动分配id相匹配,那么该节点将立即恢复该主分片

  • cluster.routing.allocation.node_concurrent_incoming_recoveries:一个节点上允许多少个并发恢复传入进来的分片。默认是2
  • cluster.routing.allocation.node_concurrent_outgoing_recoveries:一个节点上允许多少并发输出需要恢复的分片数量。默认是2
  • cluster.routing.allocation.node_initial_primaries_recoveries:虽然副本的恢复是通过网络进行的,但节点重启后未分配的主分片的恢复使用来自本地磁盘的数据。这种方式是很快速的,可以在同一个节点上并行的恢复未分配的主分片。默认值为4
  • cluster.routing.allocation.same_shard.host:允许根据主机名和主机地址执行检查以防止在单个主机上分配同一分片的多个实例。默认为 false,意味着默认情况下不执行任何检查。此设置仅适用于在同一台计算机上启动多个节点的情况
# 未修改前配置
bash-4.2$ curl -u elastic:elastic http://localhost:9200/_cluster/settings
{"persistent":{"action":{"auto_create_index":"-rainbow-r-*,-rainbow-w-*"}},"transient":{}}

# 修改集群配置(永久生效)
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"persistent": {
		"cluster.routing.rebalance.enable": "all",
		"cluster.routing.allocation.node_concurrent_incoming_recoveries": 2,
		"cluster.routing.allocation.node_concurrent_outgoing_recoveries": 2,
		"cluster.routing.allocation.node_concurrent_recoveries": 2,
		"cluster.routing.allocation.node_initial_primaries_recoveries": 4,
		"cluster.routing.allocation.same_shard.host": false
	}
}'

# es节点重启后,查询配置,可以发现实际还是生效了
bash-4.2$ curl -u elastic:elastic http://localhost:9200/_cluster/settings
{"persistent":{"action":{"auto_create_index":"-rainbow-r-*,-rainbow-w-*"},"cluster":{"routing":{"rebalance":{"enable":"all"},"allocation":{"node_concurrent_incoming_recoveries":"2","node_concurrent_recoveries":"2","node_initial_primaries_recoveries":"4","same_shard":{"host":"false"},"node_concurrent_outgoing_recoveries":"2"}}}},"transient":{}}


# 修改集群配置(临时生效)
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"cluster.routing.rebalance.enable": "all",
		"cluster.routing.allocation.node_concurrent_incoming_recoveries": 2,
		"cluster.routing.allocation.node_concurrent_outgoing_recoveries": 2,
		"cluster.routing.allocation.node_concurrent_recoveries": 2,
		"cluster.routing.allocation.node_initial_primaries_recoveries": 4,
		"cluster.routing.allocation.same_shard.host": false
	}
}'

分片重新平衡设置

​ 当集群中的每个节点上具有相同数量的分片时,集群是平衡的。Elasticsearch 运行一个称为自动重新平衡的进程,它在集群中的节点之间移动分片以改善其平衡。重新平衡遵循所有其他分片分配规则,例如 allocation filtering 和forced awareness ,这可能会阻止它完全平衡集群。在这种情况下,重新平衡会努力在您配置的规则内实现最平衡的集群。如果您使用data tiers ,那么 Elasticsearch 会自动应用分配过滤规则将每个分片放置在适当的层中。这些规则意味着平衡器在每一层内独立工作。您可以使用以下设置来控制集群中分片的重新平衡:

cluster.routing.rebalance.enable:(动态)为特定类型的分片启用或禁用重新平衡:

  • all -(默认)允许对所有类型的分片进行分片平衡
  • primaries - 只允许主分片的分片平衡
  • replicas- 仅允许对副本分片进行分片平衡
  • none - 任何索引都不允许进行任何类型的分片平衡

cluster.routing.allocation.allow_rebalance:指定何时允许分片重新平衡:

  • always - 始终允许重新平衡
  • index_primaries_active - 仅当集群中的所有主节点都已分配时
  • index_all_active -(默认)仅当集群中的所有分片(主分片和副本)都被分配时

cluster.routing.allocation.cluster_concurrent_rebalance:集群范围内,允许多少个并发来进行分片重新分配。默认为2。注意,此设置仅控制由于集群中的不平衡而导致的并发分片重定位的数量

# 修改集群配置(永久生效)
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"persistent": {
		"cluster.routing.rebalance.enable": "all",
		"cluster.routing.allocation.allow_rebalance": "always",
		"cluster.routing.allocation.cluster_concurrent_rebalance": "2"
	}
}'


# 修改集群配置(临时生效)
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"cluster.routing.rebalance.enable": "all",
		"cluster.routing.allocation.allow_rebalance": "always",
		"cluster.routing.allocation.cluster_concurrent_rebalance": "2"
	}
}'

重新平衡系数设置

再平衡是根据每个节点分配的分片计算其权重,然后在节点之间移动分片,以减少较重节点的权重,增加较轻节点的权重。当不存在可能的分片移动时,集群是平衡的,分片移动可以使任何节点的权重比任何其他节点的权重更接近一个可配置的阈值。以下设置允许您控制这些计算的详细信息

  • cluster.routing.allocation.balance.shard:定义节点上分配的分片总数的权重因子(浮点数)。默认为0.45f。提高这个值就会使集群中所有节点的分片数量趋于相等
  • cluster.routing.allocation.balance.index:定义在特定节点上分配的每个索引的分片数量的权重因子(浮动)。默认为0.55f。提高这个值会使集群中所有节点的每个索引的分片数量趋于相等
  • cluster.routing.allocation.balance.threshold:提高将导致集群在优化碎片平衡方面不那么积极

基于磁盘容量的shard分配

基于磁盘的碎片分配器确保所有节点都有足够的磁盘空间,而不会执行超出范围的碎片移动。它根据低水印和高水印的阈值分配碎片。它的主要目标是确保没有节点超过高水印线,或者至少任何这样的超限都只是暂时的。如果一个节点超过了高水印线,Elasticsearch将通过将其部分分片移动到集群中的其他节点上来解决这个问题。节点暂时超过高水位是正常现象

分配器还试图通过禁止向超过低水位的节点分配更多的分片来保持节点远离高水位。重要的是,如果您的所有节点都超过了低水位,那么就不能分配新的分片,Elasticsearch将无法在节点之间移动任何分片,以保持磁盘使用率低于高水位。您必须确保集群总有足够的磁盘空间,并且总有一些节点低于低水位

如果节点填满其磁盘的速度比 Elasticsearch 将分片移动到其他地方的速度快,则存在磁盘完全填满的风险。为了防止这种情况,作为最后的手段,一旦磁盘使用量达到洪水水印阶段,Elasticsearch 将阻止向受影响节点写入索引分片。它还将继续将分片移动到集群中的其他节点上。当受影响节点上的磁盘使用率低于高水位线时,Elasticsearch 会自动删除写入块
您可以使用以下设置来控制基于磁盘的分配:

  • cluster.routing.allocation.disk.threshold_enabled:默认为true。设置为false可禁用磁盘分配器
  • cluster.routing.allocation.disk.watermark.low
    • 控制磁盘使用的低水印。默认为 85%,意味着 Elasticsearch 不会向磁盘使用率超过 85% 的节点分配分片。它也可以设置为绝对字节值(如 500mb)以防止 Elasticsearch 在可用空间少于指定量时分配分片。此设置对新创建索引的主分片没有影响,但会阻止分配它们的副本
    • 磁盘使用超过这个阈值,就认为“危险”快来了,这个时候就不会往该节点再分配replica shard了,但新创建的索引的primary shard还是可以分配。特别注意必须是新创建的索引(什么是“老的”?比如再平衡时其它节点上已经存在的primary shard就算老的,这部分也是不能够迁移到进入low watermark的节点上来的)
  • cluster.routing.allocation.disk.watermark.high
    • 控制高水位。默认值为90%,这意味着Elasticsearch将尝试将分片从磁盘使用率超过90%的节点上迁移。也可以将其设置为绝对字节值(类似于低水印),以便在节点的空闲空间小于指定数量时将分片移离节点。此设置会影响所有分片的分配,无论之前是否已分配
    • 磁盘使用超过这个阈值,就认为“危险”已经来了,这个时候不会再往该节点分配任何shard,即primary shard和replica shard都不会分配。并且会开始尝试将节点上的shard迁移到其它节点上
  • cluster.routing.allocation.disk.watermark.enable_for_single_data_node:对于单个数据节点,在做出分配决策时默认是忽略磁盘水印。这是不推荐使用的行为,将在 8.0 中更改。可以将此设置设置为 true 以启用单个数据节点集群的磁盘水印
  • cluster.routing.allocation.disk.watermark.flood_stage
    • 控制洪水阶段水印,默认为95%。当超过这个阀值的时候,Elasticsearch在每个索引上强制执行只读索引块。此设置是防止节点耗尽磁盘空间的最后手段。当磁盘利用率低于高水位线时,索引块将自动释放
    • 磁盘使用超过这个阈值,就认为已经病入膏肓了,需要做最后的挽救了,挽救方式也很简单——断臂求生:将有在该节点上分配shard的所有索引设置为只读,不允许再往这些索引写数据,但允许删除索引(index.blocks.read_only_allow_delete)
    • 当有磁盘使用超过洪水线,elasticsearch会强制停止所有写入操作
  • cluster.routing.allocation.disk.watermark.flood_stage.frozen
  • cluster.routing.allocation.disk.watermark.flood_stage.frozen.max_headroom
  • cluster.info.update.interval:Elasticsearch 应该多久检查一次集群中每个节点的磁盘使用情况。默认为 30

您不能在这些设置中混合使用百分比值和字节值。要么将所有值设置为百分比值,要么将所有值设置为字节值。这样做是为了让Elasticsearch能够验证设置在内部是一致的,确保低磁盘阈值小于高磁盘阈值,高磁盘阈值小于洪水阶段阈值

在7.4.0及以后版本,一旦检测到磁盘使用率低于阈值后,会自动恢复;7.4.0以前的版本,必须手动执行以下命令来取消只读状态

大概总结一下:

  1. 当进入low watermark的时候,就放弃新创建的索引的副本分片数据了(即不创建对应的shard),但还是允许创建主分片数据
  2. 当进入high watermark的时候,新创建索引的主分片、副本分片全部放弃了,但之前已经创建的索引还是可以正常继续写入数据的;同时尝试将节点上的数据向其它节点迁移
  3. 当进入flood stage watermark,完全不允许往该节点上写入数据了,这是最后一道保护。只要在high watermark阶段,数据可以迁移到其它节点,并且迁移的速度比写入的速度快,那就不会进入该阶段
# 当空闲磁盘低于800mb时进入low watermark;低于600mb时进入high watermark;低于500mb时进入flood stage;每10秒检查一次
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "800mb",
    "cluster.routing.allocation.disk.watermark.high": "600mb",
    "cluster.routing.allocation.disk.watermark.flood_stage": "500mb",
    "cluster.info.update.interval": "10s"
  }
}

集群只读

参考链接:https://cloud.tencent.com/document/product/845/56276

数据节点的磁盘使用率存在以下三个水位线,超过水位线可能会影响 Elasticsearch 或 Kibana 服务

  • 当集群磁盘使用率超过85%:会导致新的分片无法分配。

  • 当集群磁盘使用率超过90%:Elasticsearch 会尝试将对应节点中的分片迁移到其他磁盘使用率比较低的数据节点中。

  • 当集群磁盘使用率超过95%:系统会对 Elasticsearch 集群中对应节点里每个索引强制设置 read_only_allow_delete 属性,此时该节点上的所有索引将无法写入数据,只能读取和删除对应索引

查询是否只读
# 如果 cluster.blocks.read_only 的值为 true,则表示集群处于只读模式
bash-4.2$ curl -u elastic:elastic localhost:9200/_cluster/settings?pretty=true
{
  "persistent": {},
  "transient": {},
  "defaults": {
    "cluster": {
      "blocks": {
        "read_only": "false"
      }
    }
  }
}


# 如果 index.blocks.read_only 的值为 true,则表示该索引处于只读模式
bash-4.2$ curl -u elastic:elastic localhost:9200/rainbow*/_settings?pretty=true
{
  "your_index": {
    "settings": {
      "index": {
        "blocks": {
          "read_only": "false"
        }
      }
    }
  }
}
清理集群数据修复
# 1. 开启集群索引批量操作权限(临时生效)
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"action.destructive_requires_name": "false"
	}
}'

# 2. 批量删除不需要的索引,待磁盘正
	curl -u elastic:elastic -X DELETE "http://localhost:9200/test1,test2,test3"
	curl -u elastic:elastic -X DELETE "http://localhost:9200/rainbow*"

# 3. 关闭索引只读
curl -u elastic:elastic -X PUT "http://localhost:9200/_all/_settings" -H 'Content-Type: application/json' -d'{
	 "index.blocks.read_only_allow_delete": null
}'

# 4. 关闭集群只读状态
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"persistent": {
		 "cluster.blocks.read_only_allow_delete": null
	}
}'

# 5. 取消临时设置的批量操作权限
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"action.destructive_requires_name": null
	}
}'
磁盘扩容
  • 待磁盘扩容正常后
# 1. 关闭集群只读状态
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"persistent": {
		 "cluster.blocks.read_only_allow_delete": null
	}
}'

# 2. 取消临时设置的批量操作权限
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"action.destructive_requires_name": null
	}
}'

手动重新平衡

# 临时关闭集群自动分配迁移,防止reroute的时候触发shard分片迁移
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"cluster.routing.rebalance.enable": "none"
	}
}'

# 重新分配分配(将哪些失败的重新分配)
curl -u elastic:elastic -XPOST "http://localhost:9200/_cluster/reroute?retry_failed=true&explain=true&pretty=true"


# 临时关闭设置的参数(保证原本的参数配置),todo
curl -u elastic:elastic -X PUT "http://localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{
	"transient": {
		"cluster.routing.rebalance.enable": "none"
	}
}'
  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺仔_牛奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值