大数据&云计算JVM · Java虚拟机原理 · JVM上语言·框架· 生态系统玩转大数据

Elasticsearch ILM Shrink Action源

2022-02-17  本文已影响0人  bellengao

1. 背景

在之前的一篇文章"PB级大规模Elasticsearch集群的运维与调优实践"中,指出了在集群每天产生大量分片,并且索引不能删除的情况下,需要对比较老的索引通过配置ILM策略进行Shrink,比如从60分片shrink到5或者10分片,从而从整体上降低集群整体的分片数量,避免集群不稳定现象的发生。

以某个客户的使用场景为例,客户采用按小时创建索引的方式,单日会产生2880个分片,集群运行了一段时间后总的分片数量就达到了10w:

过多的分片带来的影响是比较大的,不仅会影响写入,还会影响master节点处理任务的效率,过多分片的元数据也会占用较多内存,导致master节点出现无法响应的情况:

2. 一般的优化手段

为了解决集群分片数过多,通常的做法就是通过配置索引生命周期策略,定期清理过期的数据,或者去掉副本,甚至拆分集群;但是客户的要求是数据一条也不能删,并且需要保证数据的可靠性、一个业务也只能使用一个集群;所以一般的解决方法解决不了客户的问题,因此针对客户的需求我也制定了一系列的优化措施,给索引的生命周期设置了四个阶段,并分别从降低索引粒度,数据冷备去副本,开启Shrink这几个角度进行了优化,其中Shrink特性最能降低集群分片数,在索引创建超过60天后,进入到Warm阶段,就把索引从60分片,缩到10分片,分片数就降低了83%。

image

经过这些优化,预期可以把每个月新增的分片数降低到3600,但是运行了一段时间后发现并没有达到预期。

在上述优化方案实施了一段时间后,客户反馈偶尔地收到集群Red的告警,经过排查,发现是Shrink出来的新索引会偶现red,也会出现部分节点负载比较高的情况,最严重的是一部分索引的Shrink任务会卡住,导致每个月新增的分片数并没有下降到预期。

Shrink任务存在的问题:

针对这些问题,临时的解决办法是通过python脚本来进行批量处理,但是通过python脚本进行处理的方式毕竟不够通用,所以下定决心去研究ES内核中的Shrink这个特性。

3. 优化Shrink Action

带着碰到的问题去研究源码,也理清了Shrink任务的所有执行步骤,步骤比较多,实现也比较复杂:


image

之后总结并归纳了Shrink任务的核心步骤,也是最容易出问题的三个步骤:

Step 1. 第一步是选择一个节点,作为将要执行Shrink的节点
Step 2. 第二步把原始索引的分片都移动到选择的节点上,主分片和副本分片均可,只要有一份完整的拷贝就可以
Step 3. 第三步构建一个新的分片数量少的索引,通过别名完成新旧索引的切换,从而达到降低索引分片数的目的。

image

接下来带着已知的问题,逐步去优化Shrink任务的这三个步骤。

3.1 优化Select Node节点选择步骤

3.1.1 从磁盘空间角度优化

在节点选择步骤,原生内核存在以下问题:

因此先从磁盘空间的角度进行优化:

经过对节点选择步骤从磁盘空间角度进行优化,解决了一部分Shrink任务卡住问题以及Shunken索引Red的问题。

image
相关PR:https://github.com/elastic/elasticsearch/pull/76206

3.1.2 从节点属性角度优化

在节点选择步骤,原生内核还存在以下问题:

因此,又从节点属性的角度进行了优化:

从节点属性的角度进行的这些优化,又解决了另外一部分Shrink任务卡住的问题。

image
image
相关PR:https://github.com/elastic/elasticsearch/pull/65037 , https://github.com/elastic/elasticsearch/pull/67137

3.1.3 从减少分片移动的角度优化

在解决任务卡住和索引Red问题的过程中,又发现了原生的内核在选择节点时还存在的一个问题:

所以从减少分片移动的角度又进行了优化,优化策略是优先选择本身已经包含当前索引分片的节点,但是还存在按照分片数量还是分片总容量优先的问题。


image

在90%的场景下,数据在各个分片都是均匀分布的,分片数量最多的节点就是分片总容量最大的节点,这时候选择分片总容量最大的节点是没有问题的;但是仍然需要考虑剩下10%的数据分布不均的场景,经过对比测试,移动较大的分片相对小的分片,在耗时和系统资源消耗上都会高不少,最终确定优先选择分片总容量最大的节点,既减少分片迁移的时间,也降低了系统资源的消耗。

image
相关PR:https://github.com/elastic/elasticsearch/pull/76206

3.2 优化Reroute Shards移动分片步骤

紧接着是优化第二个步骤,Reroute shards, 这一步是在上一步选择了节点之后,把索引的分片都移动到这个节点上,原生内核在这一步骤存在以下两个问题:

所以又从索引属性的角度分别对以上问题进行了优化:

相关PR:https://github.com/elastic/elasticsearch/pull/74219

3.3 优化Exec Shrink步骤

接下来是优化第三个步骤,执行Shrink, 原生内核里,对于要shrink到多少个分片,数量是固定的,比如60个分片,只能选择shrink到10或者20个分片:


image

但是索引容量有大有小,都shrink到10个分片的话,就会出现分片容量忽大忽小的问题:


image
这就不符合我们常说的一个准则,一个分片容量大小在30-50GB时可以获得较好的性能,这样做的原因有很多,总结来说就是分片过大过小都会影响集群性能:

在发现了这个问题之后,前期也通过python脚本进行了优化,但是毕竟不能通用,所以决定去优化内核,在这一步骤中,增加了设置基准分片容量大小的参数,计算出最佳的目标分片数:

image
相关PR:https://github.com/elastic/elasticsearch/pull/67705,
https://github.com/elastic/elasticsearch/pull/68502

比如以50GB为基准,不同容量大小的索引Shrink到不同的分片数,从而使得单分片的容量不会超过50GB,大部分的索引都可以保持在30-50GB:


image

另外一方面,因为客户的业务高峰期持续时间不长,100-500GB的索引居多,所以这个优化还可以进一步降低集群整体的分片数。

从对比测试的结果来看,保持分片在50GB,相比较100GB以上的大分片,分片恢复以及分片迁移的时间都可以降低不少,另外所以这个优化还可以把集群整体的分片数量再次降低10%左右。


image
image
image

经过上述一系列的优化,整体的优化效果如下:

经过这次对ILM中的Shrink Action的优化,我总结了解决一些棘手问题的方法,就是要从实际场景出发,去解决核心问题,最重要的是要把想法变成现实。 在解决Shrink的问题之后,也尝试去思考怎么从源头避免产生大量分片,而不是出了问题之后再去解决,目前在云上已经实现了分片数量的自动化巡检,并且主动给客户提供改进优化的建议,未来也规划实现写入托管,按分片大小滚动创建索引,使得用户无需关心集群整体的分片数量等问题。

上一篇下一篇

猜你喜欢

热点阅读