前言
Elasticsearch 是一款开源的搜索引擎,采用 Lucene 进行底层搜索实现。近年来,随着数据量的增加以及用户量的提升,Elasticsearch 受到了越来越多的关注。然而随之而来的是性能问题。如何优化 Elasticsearch 的性能,成为了前端工程师和后端工程师们需要面对的一个重要问题。本文将介绍 Elasticsearch 性能优化实践,帮助大家更好地解决这个问题。
1. 坑位总结
1.1 确认集群状态
首先在 Elasticsearch 集群出现问题的时候,我们需要确定集群状态。通过命令行输入下面的命令,可以查询集群状态:
curl -XGET http://localhost:9200/_cluster/health?pretty
在控制台中显示了诸如 red
、yellow
、green
等字符串,代表了不同的集群状态。
red
表示集群状态不好,存在主分片未分配。yellow
表示集群状态不错,但是存在次要分片未分配。green
表示集群状态非常好,所有分片都已被分配。
如果 Elasticsearch 集群的状态为红色,那么一定要仔细看一下什么导致了这个问题。如果是主分片未分配,则需要调整副本数量和分片数量等参数,通过命令 curl -XPUT http://localhost:9200/_settings -d '{ "index" :{ "number_of_replicas" : 1 } }'
可以将副本数改为 1 个。如果是次要分片未分配,则有可能是硬件故障导致,需要确定哪些硬件故障了,并更换或者修复它。
1.2 调整分片数量
分片数量会影响 Elasticsearch 性能,保证分片数量合理兼顾性能和稳定性非常重要。一般来说,Elasticsearch 的一个分片大小应该在 50GB 左右。如果分片太小,则显然会引起查询效率慢的问题,如果分片太大,则可能会导致集群的稳定性问题。
最佳实践是对于数据特别多的索引设置 3 到 5 个分片,而对于数据较少的索引则只设置 1 到 2 个分片。如果确认索引大小后发现其超过了 50GB,那么就应该增加分片数量,例如可以将分片数量从 5 个改为 10 个。
curl -XPUT 'http://localhost:9200/myindex/_settings' -d '{"settings":{"number_of_shards":10}}'
需要注意的是,分配新的分片会会耗费一定时间,甚至会导致集群压力过大而崩溃。因此,切记不要过于频繁地进行分片调整。
1.3 设置合理的 heap 内存
Elasticsearch 在初始化的时候会预留一个固定的内存大小,用于缓存常用的数据结构。这个内存区域也被称为 heap 内存。heap 太大或太小都会导致 Elasticsearch 的性能下降。在通常情况下,Elasticsearch 的 heap 大小应该设置为 50% 至 80% 的物理内存大小,但是不应该超过 32GB。
ES_JAVA_OPTS="-Xms4g -Xmx4g" bin/elasticsearch
当 Elasticsearch 内存占用超过设定的上限后,会导致 JVM 垃圾回收(GC)过于频繁,导致集群响应变慢,降低 Elasticsearch 的性能。因此,合理设置 heap 大小非常重要。
1.4 增加主分片副本数量
在 Elasticsearch 中,我们可以通过增加主分片副本数量的方式来提高性能。主分片负责存储数据,副本负责数据的冗余备份。我们可以通过设置 number_of_replicas
参数来增加主分片副本数量。然而,过多地增加副本数量会导致集群性能下降。
一些最佳实践建议为数据集固定并且小于 50GB 的索引设置 1 个主分片和 1 个副本分片。对于数据集固定但大于 50GB 的索引,可以设置 2 个主分片和 1 个副本分片。对于不断扩张的数据集,可以使用 5 个主分片和 1 个副本分片的设置。
2. 性能优化建议
2.1 确定索引存储方式
在 Elasticsearch 中,Lucene 中的“索引”是数据的物理表示形式。它是一个由一组记录组成的文件集合,用于找到文档与搜索请求之间的匹配相似之处。Elasticsearch 允许用户选择两种不同的方式存储索引,其中一个是 mmap
映射存储方式,另一个是 nfs
存储方式。
在一些场景中,mmap
映射存储方式会带来更好的性能。例如,如果数据集小并且热数据完全在内存中,则 mmap
存储方式可以通过提高搜索效率来提高性能。另一方面,nfs
存储方式则可以让用户更快地启动 Elasticsearch 节点并快速重启。可以通过设置 path.data
、path.work
和 path.logs
等参数来选择存储方式。例如:
path.data: /var/lib/elasticsearch path.work: /tmp/elasticsearch/work path.logs: /var/log/elasticsearch
2.2 利用缓存机制
Elasticsearch 借助 Lucene 缓存机制提供了与基于索引模型的库(如 Solr 等)相似的缓存机制。它内置的缓存分为两种,一种是倒排索引缓存(doc ID、term 等),另一种是字段数据缓存。可以通过增加缓存大小来提高 Elasticsearch 的性能。
curl -XPUT 'http://localhost:9200/myindex/_settings' -d '{"index.cache.field.max_size":"20%", "index.cache.field.expire":"10m"}'
然而,最佳实践同时也提醒:不要将缓存设置得太大,否则会占用过多内存。一般来说,最佳的实践是设定 20% 到 30% 的字段数据缓存大小。
2.3 使用 Filters
在 Elasticsearch 中,我们可以使用 Filters 来对查询进行优化。Filters 排除所有不匹配的文档,而不是将所有符合条件的文档存储到内存中并进行搜索。这提高了查询性能,并大大加速了 Elasticsearch 的索引速度。
-- -------------------- ---- ------- ---- ----- ---------------------------------------------- -- - - -------- - ----------- - -------- - -------- - -------- ------ - -- --------- - ------- - ---------- ------ - - - - --
2.4 索引自动模板
在 Elasticsearch 中,模板是一种可以帮助用户自动化索引创建并自动管理索引的机制。模板定义了一个索引模式,用于自动为新的索引分配分片/副本、设置未设置的配置等。模板还可以为动态模板设置分片、副本,以及其他索引参数值。例如:
-- -------------------- ---- ------- --- -------------------- - ----------- ------------- ----------- - ------------------- -- --------------------- -- ------------------------- ---- -- ----------- - ---------- - ------------- - ---------- -------- ---------- -------------- -------- ------- --------- -------------------- ------- -------- --------- - - - -
上述代码创建了一个包含 5 个分片和 1 个副本的索引模板,并将刷新时间设置为每 5 秒钟。该模板还创建了一个名为 fluentd 的动态模板。Elasticsearch 生命周期的关键部分可以通过模板的设置进行自动化,从而优化 Elasticsearch 的性能。
2.5 利用 Bulk API 处理数据
Elasticsearch 的 Bulk API 可以帮助我们在处理大量数据时提高索引速度。Bulk API 允许我们将数百个文档一次性加载到 Elasticsearch 中,并将其存储在同一索引中。这通常比单独对每个文档进行索引更快。例如:
curl -XPOST 'http://localhost:9200/myindex/mytype/_bulk' -d ' { "index": {}} { "name": "John Doe" } { "index": {}} { "name": "Jane Smith" } '
在上述代码中,我们一次性加入了两个文档到 myindex 索引中。
需要注意的是,当使用 Bulk API 进行数据处理时,必须保持单个请求的大小在 100MB 左右。同时,也不要在单个文档中存储超过 Elasticsearch 节点的内存大小。
总结
本文介绍了 Elasticsearch 性能优化的一些重要坑位以及优化建议。在实际开发中,我们应该结合实际情况,合理配置分片/副本、heap 内存、缓存机制等各项参数。同时,我们也需要注意 Index Head 节点的使用,轻度复制机制的启用以及使用 Filter、Bulk API 等特性优化 Elasticsearch 的性能。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6469eb02968c7c53b09b2aca