elasticsearch的shard优化

本文详细介绍了Elasticsearch中的分片概念及其重要性,包括刷新和合并过程。讨论了过多或过小分片可能带来的问题,如集群状态过大、资源竞争和查询效率下降,并提供了相应的优化策略,如合理设定分片大小、控制索引数量和使用shrink index API。建议每个分片大小保持在20GB至40GB之间,同时注意节点内存与分片数量的平衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shard简介

Elasticsearch 中的数据会整理为索引。每个索引又由一个或多个分片组成。每个分片都是一个 Lucene 索引实例,您可以将其视作一个独立的搜索引擎,它能够对 Elasticsearch 集群中的数据子集进行索引并处理相关查询。
分片是 Elasticsearch 在集群内分发数据的单位。Elasticsearch 在对数据进行再平衡(例如发生故障后)时移动分片的速度取决于分片的大小和数量,以及网络和磁盘性能。

刷新

数据写到分片上周,会定期写到磁盘上不可更新的lucene段中,这个时候数据遍可以查询了,这个就是刷新。

合并

随着段数越来越多,这些段会定期合并为更大的段。这一过程称为合并。由于所有段都是不可更改的,这意味着在索引期间所用磁盘空间通常会上下浮动,这是因为只有合并后的新段创建完毕之后,它们所替换的那些段才能删掉。合并是一项极其耗费资源的任务,尤其耗费磁盘 I/O。

index可能带来的问题

对于每个 Elasticsearch 索引,mapping映射和状态的相关信息都存储在集群状态中。这些信息存储在内存中,以便快速访问。因此,如果集群中的索引和分片数量过多,这会导致集群状态过大,如果mapping映射较大的话,尤为如此。这会导致更新变慢,因为所有更新都需要通过单线程完成,从而在将变更分发到整个集群之前确保一致性。

解决

  1. 对于数据量小的数据,可以使用一个固定名字或者按照月/年存储数据到index,有助于减少存储在集群中的索引和分片数量。
  2. 相似数据结构的数据都存储到一个index中,有助于减少存储在集群中的索引和分片数量。

shard可能带来的问题

  1. 一个shard底层为一个lucene索引,会消耗一定文件句柄,内存,cpu等。例如堆内存会存储分片级别以及段级别信息的数据结构,因为只有这样才能确定数据在磁盘上的存储位置。这些数据结构的大小并不固定,不同用例之间会有很大的差别。
  2. 每个search请求都需要命中index中的shard,如果每一个shard都处于不同的节点还好,如果多个shard都需要在同一个节点上竞争使用相同的资源,可能导致效率降低。
  3. 用于计算相关度的词项统计信息是基于分片的。如果有许多分片,每一个都只有很少的数据会导致很低的相关度。
  4. 在 Elasticsearch 中,每个查询都是在单个分片上以单线程方式执行的。然而,可以同时对多个分片进行处理。这意味着,最低查询延时(假设没有缓存)将取决于数据、查询类型,以及分片大小。尽管查询很多个小分片会加快单个分片的处理速度,但是由于有很多任务需要进入队列并按顺序加以处理,所以与查询较少的大分片相比,这种方法并不一定会加快查询速度。如果有多个并发查询,拥有很多(成百上千)小分片还会降低查询吞吐量。
  5. shard过大,导致集群故障后恢复缓慢,写入放大,导致  bulk queue打满,拒绝率上升
  6. shard过小,导致shard的段过小,无法充分利用多节点资源,机器资源不均衡,影响段合并效率和浪费资源

优化shard的办法

  • shard大小官方通常建议介于20GB至40GB之间
  • 尽管并没有关于shard大小的固定限值,但是官方建议将50GB作为shard大小的上限。
  • 多个shard尽量分布再不同的节点。因为一个index对应的shard在每个节点分配一个对性能提升最好。考虑到高可用和吞吐量,shard是需要配置副本的,故建议根据此公式平衡节点数量,主shard,shard副本的关系:

Max number of nodes = Number of primary shards * (number of primary shard replicas +1)

  • 对于数据量小的数据,可以使用一个固定名字或者按照月/年存储数据到index,有助于减少存储在集群中的索引和分片数量。
  • 建议把每天的数据存储到按照天命名的index中。此类index允许用户在很细的粒度层面管理保留期,也方便用户根据每天不断变化的数据量轻松进行调整,也有助于降低单个shard的大小。
  • 相似数据结构的数据都存储到一个index中,有助于减少存储在集群中的索引和分片数量。
  • 使用shrink index API把数据量小且使用了多个shard的index压缩成较少shard的index。
  • 确保对于节点上已配置的每个GB堆内存,将分片数量保持在20以下。如果某个节点拥有30GB的堆内存,那其最多可有600个分片,但是在此限值范围内,您设置的分片数量越少,效果就越好。

每个节点的 maximum shards open 设置为多大合适

es 7.x 版本后默认单个节点最大分片数为1000。对于分片数的大小,业界一致认为分片数的多少与内存挂钩,认为 1GB 堆内存对应 20-25 个分片。

每个节点可以存储的分片数和可用的堆内存大小成正比关系。

Elastic 官方博客文章建议:堆内存和分片的配置比例为1:20,举例:30GB堆内存,最多可有600个分片。因此,具有30GB堆的节点最多应有600个分片,但是越低于此限制,您可以使其越好。而一个分片的大小不要超过50G,通常,这将有助于群集保持良好的运行状况。

总结

es中并不是shard数量越多越好,也不是shard越小越好,要根据实际情况来优化shard相关参数。

### 关于ElasticSearchShard Size的理解 在Elasticsearch中,并不存在直接名为`shard_size`的参数用于配置分片大小。实际上,分片的大小是由多个因素共同决定的,包括但不限于文档的数量、每条记录的平均体积以及存储这些数据所需的元数据量。 #### 影响分片实际大小的因素 - **文档数量**:更多的文档通常意味着更大的分片。 - **单个文档尺寸**:较大的文档也会增加分片的整体规模。 - **索引模式复杂度**:复杂的映射结构可能会占用更多空间来保存额外的信息[^2]。 为了间接控制分片的实际大小,在创建索引时可以考虑以下几个方面: 1. **预估合理的初始分片数目** 可以通过估算预期的数据总量除以理想的单个分片最大容量(一般建议不超过几十GB),从而得出合适的初始分片数目的设定。这有助于防止因过早达到硬件资源极限而导致性能下降的情况发生。 2. **利用rollover API实现动态管理** 当前版本提供了Rollover机制允许基于条件自动滚动创建新的索引,这样可以在不中断服务的情况下灵活应对不断增长的数据流。例如当现有索引内的总字节数达到了指定阈值之后就会触发新索引的建立过程。 3. **优化写入操作频率与批量提交策略** 减少不必要的更新请求次数并通过适当增大批次处理量的方式降低频繁刷新带来的开销,进而影响到最终形成的分片文件大小。 ```json POST /_aliases { "actions" : [ { "add" : { "index" : "my-index-write", "alias" : "my-index-read" } }, { "remove_index" : { "index" : "old-index-name" } } ] } ``` 此命令展示了如何使用别名切换当前正在写的索引来支持rollover功能的一部分逻辑。 4. **定期执行force merge操作** 这一措施可以帮助压缩已存在的段落减少碎片化现象的发生,使得后续新增加的内容更容易被合理分配至各个现有的物理分区当中去。 ```bash POST my-index/_forcemerge?max_num_segments=5 ``` 上述命令将尝试把目标索引内部的所有Lucene segment合并成最多五个大segment,以此方式有效减小了整体所占的空间并提高了检索效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

magic_kid_2010

你的支持将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值