摘要:Elasticsearch是基于Apache Lucene的开源搜索和分析引擎,允许用户以近乎实时的方式存储,搜索和分析数据。虽然Elasticsearch专为快速查询而设计,但其性能在很大程度上取决于用于应用程序的场景,索引的数据量以及应用程序和用户查询数据的速率。这篇文章概述了挑战和调优过程,以及Pronto团队以战略方式构建应对挑战的工具。它还以各种图形配置展示了进行基准测试的一些结果。以下是正文。
Elasticsearch是基于Apache Lucene的开源搜索和分析引擎,允许用户以近乎实时的方式存储,搜索和分析数据。Pronto是在eBay网站上托管Elasticsearch集群的平台,该平台使得eBay网内部客户易于部署,操作用于全文搜索,实时分析和日志/事件监控的大规模的Elasticsearch。当前Pronto平台管理着60多个Elasticsearch集群和2000多个节点,日采集量达到180亿份文档,日均搜索请求达到35亿份。平台提供从条款,补救以及安全到监控,报警和诊断的全方位的信息。
虽然Elasticsearch专为快速查询而设计,但其性能在很大程度上取决于用于应用程序的场景,索引的数据量以及应用程序和用户查询数据的速率。这篇文章概述了挑战和调优过程,以及Pronto团队以战略方式构建应对挑战的工具。它还以各种图形配置展示了进行基准测试的一些结果。
迄今为止所观察到的Pronto / Elasticsearch使用案例面临的挑战包括:
为了帮助客户应对这些挑战,Pronto团队从用户案例开始入手并持续整个集群生命周期,构建性能测试、调优和监控的战略方法。
Pronto团队为每种类型的机器和每个支持的Elasticsearch版本运行基准测试,以收集性能数据,然后将其与客户提供的信息一起用于评估集群的初始大小,这些信息包括:
在开始摄取数据并运行查询之前,请三思而后行。索引代表着什么?Elastic的官方回答是“具有相似特征的文档集合”。那么下一个问题是“应该使用哪些特征来对数据进行分组?应该把所有文件放入一个索引还是多个索引呢?”答案是,这取决于所使用的查询。下面是关于如何根据最常用的查询分组索引的一些建议。
{ "query": { "bool": { "must": { "match": { "title": "${title}" } }, "filter": { "term": { "region": "US" } } } } }
在这种情况下,如果索引按照美国,欧洲等地区分成几个较小的索引,就可以获得更好的性能。然后可以从查询中删除过滤子句。如果需要运行一个跨区域查询,可以将多个索引或通配符传递给Elasticsearch。
用于索引诸如日志和监控之类的重场景,索引性能是关键指标。这里有一些建议:
性能和刷新间隔之间的关系
从上图可以看出,随着刷新间隔的增大,吞吐量增加,响应时间变快。可以使用下面的请求来检查有多少段以及刷新和合并花费了多少时间。
Index/_stats?filter_path= indices.**.refresh,indices.**.segments,indices.**.merges
性能和副本数量之间的关系
从上面的图中,可以看到随着副本数量的增加,吞吐量下降,响应时间也变慢。
使用Elasticsearch的主要原因是其支持通过数据进行搜索。用户应该能够快速地找到所需要查找的信息。搜索性能取决于很多因素:
比较查询和过滤
性能和副本数量之间的关系
从上图可以看出,搜索吞吐量几乎与副本数量成线性关系。注意在这个测试中,测试集群有足够的数据节点来确保每个分片都有一个独占节点,如果这个条件不能满足,搜索吞吐量就不会那么好。
太小的分片数量会使搜索无法扩展。例如,如果分片数量设置为1,则索引中的所有文档都将存储在一个分片中。对于每个搜索,只能涉及一个节点。如果有很多文件,那是很耗费时间的。另一方面,创建索引的分片太多也会对性能造成危害,因为Elasticsearch需要在所有分片上运行查询,除非在请求中指定了路由键,然后将所有返回的结果一起取出并合并。
根据经验来说,如果索引小于1G,可以将分片数设置为1。对于大多数情况,可以将分片数保留为默认值5,但是如果分片大小超过30GB,应该增加分片数量将索引分成更多的分片。创建索引后,分片数量不能更改,但是可以创建新的索引并使用reindex API转移数据。
在这里测试了一个拥有1亿个文档,大约150GB的索引,使用了100个线程发送搜索请求。
性能和分片数量之间的关系
从上图中可以看出,优化后的分片数量为11个。开始的时候,搜索吞吐量增加(响应时间减少),但随着分片数量的增加,搜索吞吐量减少(响应时间增加)。
请注意,在这个测试中,就像在副本数量测试中一样,每个分片都有一个独占节点。如果这个条件不能满足,搜索吞吐量就不会像上图所示那样好。
在这种情况下,建议尝试一个小于优化值的分片数,因为如果使用大分片数,并且使每个分片都有一个独占数据节点,那么就需要很多个节点。
可以使用下面的请求来检验一个节点查询缓存是否有效。
GET index_name/_stats?filter_path=indices.**.query_cache { "indices": { "index_name": { "primaries": { "query_cache": { "memory_size_in_bytes": 46004616, "total_count": 1588886, "hit_count": 515001, "miss_count": 1073885, "cache_size": 630, "cache_count": 630, "evictions": 0 } }, "total": { "query_cache": { "memory_size_in_bytes": 46004616, "total_count": 1588886, "hit_count": 515001, "miss_count": 1073885, "cache_size": 630, "cache_count": 630, "evictions": 0 } } } } }
分片查询缓存。如果大多数查询是聚合查询,应该看看分片查询缓存,它可以缓存聚合结果,以便Elasticsearch直接以低成本提供请求。有几件事情需要注意:
可以使用下面的请求来检验分片查询缓存是否有效果。
GET index_name/_stats?filter_path=indices.**.request_cache { "indices": { "index_name": { "primaries": { "request_cache": { "memory_size_in_bytes": 0, "evictions": 0, "hit_count": 541, "miss_count": 514098 } }, "total": { "request_cache": { "memory_size_in_bytes": 0, "evictions": 0, "hit_count": 982, "miss_count": 947321 } } } } }
如果某些词在索引中经常使用,但不在默认停用词列表中,则可以使用截止频率来动态处理它们。
对于每一次改变,都需要运行性能测试来验证变更是否适用。因为Elasticsearch是一个restful服务(基于RESTful web接口),所以可以使用诸如Rally,Apache Jmeter和Gatling等工具来运行性能测试。因为Pronto团队需要在每种类型的机器和Elasticsearch版本上运行大量的基准测试,而且需要在许多Elasticsearch集群上运行Elasticsearch配置参数组合的性能测试,所以这些工具并不能满足需求。
Pronto团队构建了基于Gatling的在线性能分析服务 ,帮助客户和我们运行性能测试并进行回归。该服务提供的功能使我们能够:
下图是架构
性能测试服务架构
用户可以查看每个测试的Gatling报告,并查看Kibana预定义的可视化图像,以便进一步分析和比较,如下图所示。
Gatling报告
Gatling报告
本文概述了索引/分片/副本设计以及在设计Elasticsearch集群时应该考虑的一些其它配置,以满足摄取和搜索性能的高期望。它还说明了Pronto团队如何在战略上帮助客户进行初始规模调整,索引设计和调优以及性能测试。截至今天,Pronto团队已经帮助包括订单管理系统(OMS)和搜索引擎优化(SEO)在内的众多客户实现了苛刻的性能目标,从而为eBay的关键业务做出了贡献。
Elasticsearch的性能取决于很多因素,包括文档结构,文档大小,索引设置/映射,请求率,数据集的大小,查询命中计数等等。针对一种情况的性能优化推荐不一定适用于另一种情况。彻底地测试性能,收集遥测数据,根据工作负载调整配置以及优化以满足性能要求非常重要。