0、引言
本文翻译自Elasticsearch20170918热乎的官方博客,原作者:Christian Dahlqvist。 在构建Elasticsearch集群的初期如果集群分片设置不合理,可能在项目的中后期就会出现性能问题。
Elasticsearch是一个非常通用的平台,支持各种各样的用例,并且为数据组织和复制策略提供了巨大灵活性。这种灵活性使得作为ELK新手的你将数据组织成索引和分片变得困难。虽然不一定会在首次启动时出现问题,但由于数据量随时间的推移,可能会导致性能问题。集群所拥有的数据越多,纠正问题就越困难,甚至有时可能需要重新索引大量数据。
当我们遇到遭遇性能问题的用户时,可以追溯到关于数据索引的数据和群集数量的问题并不罕见。 对于涉及multi-tenancy或使用基于时间的索引的用户尤其如此。 在与用户讨论这个问题时(会议、论坛形式),引申出的一些最常见的问题是:
1)“我应该有多少个分片?”
2)“我的分片应该有多大”?
- 1
- 2
这篇博客文章旨在帮助您回答这些问题,并为使用基于时间的索引的使用案例( 日志记录或安全分析 )提供实用的指导。
1、什么是分片?
在开始之前,让我们约定文章中用到的一些概念和术语。
Elasticsearch中的数据组织成索引。每一个索引由一个或多个分片组成。每个分片是Luncene索引的一个实例,你可以把实例理解成自管理的搜索引擎,用于在Elasticsearch集群中对一部分数据进行索引和处理查询。
【刷新】当数据写入分片时,它会定期地发布到磁盘上的新的不可变的Lucene段中,此时它可用于查询。——这被称为刷新。更详细的解读请参考:
http://t.cn/R05e3YR
【合并】随着分段数(segment)的增长,这些segment被定期地整合到较大的segments。 这个过程被称为合并(merging)。
由于所有段都是不可变的, 因为新的合并段需要创建,旧的分段将被删除 ,这意味着所使用的磁盘空间通常在索引时会波动。 合并可能资源相当密集,特别是在磁盘I/O方面。
分片是Elasticsearch在集群周围分发数据的单位。 Elasticsearch在重新平衡数据时 (例如 发生故障后) 移动分片的速度 取决于分片的大小和数量以及网络和磁盘性能。
提示:避免有非常大的分片,因为大的分片可能会对集群从故障中恢复的能力产生负面影响。 对于多大的分片没有固定的限制,但是分片大小为50GB通常被界定为适用于各种用例的限制。
2、索引有效期( retention period )
由于段是不可变的,更新文档需要Elasticsearch首先查找现有文档,然后将其标记为已删除,并添加更新的版本。删除文档还需要找到文档并将其标记为已删除。因此,删除的文档将继续占据磁盘空间和一些系统资源,直到它们被合并,这将消耗大量的系统资源。
Elasticsearch允许从文件系统直接删除完整索引,而不必明确地必须单独删除所有记录。这是迄今为止从Elasticsearch删除数据的最有效的方式。
提示:尽可能使用基于时间的索引来管理数据。根据保留期(retention period,可以理解成有效期)将数据分组。基于时间的索引还可以轻松地随时间改变主分片和副本分片的数量(以为要生成的下一个索引进行更改)。这简化了适应不断变化的数据量和需求。
3、索引和分片不是空闲的?
【集群状态】对于每个Elasticsearch索引,其映射和状态的信息都存储在集群状态。 这些集群状态信息保存在内存中以便快速访问。 因此,如果在集群中拥有大量索引,可能导致大的集群状态(特别是如果映射较大)。 所有更新集群状态操作为了在集群中保证一致性,需要通过单个线程完成,因此更新速度将变慢。
提示:为了减少索引数量并避免大的乃至非常庞大的映射,请考虑将相同索引结构的数据存储在相同的索引中,而不是基于数据的来源将数据分割成独立的索引。 在每个索引的索引数量和映射大小之间找到一个很好的平衡很重要。**
每个分片都有数据需要保存在内存中并使用堆空间。 这包括在分片级别保存信息的数据结构,也包括在段级别的数据结构,以便定义数据驻留在磁盘上的位置。 这些数据结构的大小不是固定的,并且将根据用例而有所不同。
然而,段相关开销的一个重要特征是它与分段的大小不成正比。 这意味着与较小的段相比,较大的段的每个数据量具有较少的开销,且这种差异很大。
【堆内存的重要性】为了能够每个节点存储尽可能多的数据,重要的是尽可能多地管理堆内存使用量并减少其开销。 节点拥有的堆空间越多,它可以处理的数据和分片越多。
因此,索引和分片从集群的角度看待不是空闲的,因为每个索引和分片都有一定程度的资源开销。
提示1:小分片会导致小分段(segment),从而增加开销。目的是保持平均分片大小在几GB和几十GB之间。对于具有基于时间的数据的用例,通常看到大小在20GB和40GB之间的分片。
提示2:由于每个分片的开销取决于分段数和大小,通过强制操作迫使较小的段合并成较大的段可以减少开销并提高查询性能。一旦没有更多的数据被写入索引,这应该是理想的。请注意,这是一个消耗资源的(昂贵的)操作,较为理想的处理时段应该在非高峰时段执行。
提示3:您可以在集群节点上保存的分片数量与您可用的堆内存大小成正比,但这在Elasticsearch中没有的固定限制。 一个很好的经验法则是:确保每个节点的分片数量保持在低于每1GB堆内存对应集群的分片在20-25之间。 因此,具有30GB堆内存的节点最多可以有600-750个分片,但是进一步低于此限制,您可以保持更好。 这通常会帮助群体保持处于健康状态。
4、分片的大小如何影响性能?
在Elasticsearch中,每个查询在每个分片的单个线程中执行。然而,可以并行处理多个分片,并可以在相同分片上执行多个查询和聚合。
【小分片的利弊】这意味着,在不涉及高速缓存时,最小查询延迟将取决于数据、查询的类型、分片的大小。查询大量小分片将使得每个分片的处理速度更快,但是随着更多的任务需要按顺序排队和处理,它不一定要比查询较小数量的更大的分片更快。如果有多个并发查询,则有很多小碎片也会降低查询吞吐量。
提示:从查询性能角度确定最大分片大小的最佳方法是使用逼真的数据和查询进行基准测试(真实数据而非模拟数据)。 始终使用查询和索引负载进行基准测试,代表节点在生产中需要处理的内容,因为单个查询的优化可能会产生误导性的结果。
5、如何管理分片大小?
当使用基于时间的索引时,每个索引传统上都与固定的时间段相关联。 每日索引非常普遍,经常用于持有时间区间短或每日量大的数据。 这些允许数据期限期间以良好的粒度进行管理,并且可以方便地对每天更换调整volumes。
时间周期长的数据,特别是如果每日不保存每天的索引数据,则通常会使用每周或每月的保存的碎片大小的增加。 这减少了随着时间的流逝需要存储在群集中的索引和碎片数量大小(直译有点费劲此处)。
提示:如果使用固定期限的时间索引数据,可以根据时间周期和预期数据量调整所涵盖的时间范围,以达到目标分片大小。
【均匀更新&快速变化的索引数据对比】具有固定时间间隔的基于时间的索引在数据量合理预测并且变化缓慢的情况下工作良好。 如果索引率可以快速变化,则很难保持均匀的目标分片大小。
为了能够更好地处理这种情况,推出了Rollover和S**hrink API**。 这些增加了如何管理索引和分片的灵活性,尤其适用于基于时间的索引。
此处省略了 Rollover和Shrink API的介绍。(建议查询官网补齐概念再深入)
6、结论
这篇博客文章提供了有关如何在Elasticsearch中最好地管理数据的提示和实用指南。 如果您有兴趣了解更多,推荐阅读Google搜索 “Elasticsearch: the definitive guide” (有点旧,值得阅读)。
然而,关于如何最好地在索引和分片上分发数据的许多决策将取决于用例细节,有时可能难以确定如何最佳地应用可用的建议。
文章提及的几个核心建议清单如下,以回答文章开头的提问。
1) “我应该有多少个分片?”
答: 每个节点的分片数量保持在低于每1GB堆内存对应集群的分片在20-25之间。
2) “我的分片应该有多大”?
答:分片大小为50GB通常被界定为适用于各种用例的限制。