Elasticsearch 性能优化实践

阅读时长 8 分钟读完

前言

Elasticsearch 是一款开源的搜索引擎,采用 Lucene 进行底层搜索实现。近年来,随着数据量的增加以及用户量的提升,Elasticsearch 受到了越来越多的关注。然而随之而来的是性能问题。如何优化 Elasticsearch 的性能,成为了前端工程师和后端工程师们需要面对的一个重要问题。本文将介绍 Elasticsearch 性能优化实践,帮助大家更好地解决这个问题。

1. 坑位总结

1.1 确认集群状态

首先在 Elasticsearch 集群出现问题的时候,我们需要确定集群状态。通过命令行输入下面的命令,可以查询集群状态:

在控制台中显示了诸如 redyellowgreen 等字符串,代表了不同的集群状态。

  • 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 个。

需要注意的是,分配新的分片会会耗费一定时间,甚至会导致集群压力过大而崩溃。因此,切记不要过于频繁地进行分片调整。

1.3 设置合理的 heap 内存

Elasticsearch 在初始化的时候会预留一个固定的内存大小,用于缓存常用的数据结构。这个内存区域也被称为 heap 内存。heap 太大或太小都会导致 Elasticsearch 的性能下降。在通常情况下,Elasticsearch 的 heap 大小应该设置为 50% 至 80% 的物理内存大小,但是不应该超过 32GB。

当 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.datapath.workpath.logs 等参数来选择存储方式。例如:

2.2 利用缓存机制

Elasticsearch 借助 Lucene 缓存机制提供了与基于索引模型的库(如 Solr 等)相似的缓存机制。它内置的缓存分为两种,一种是倒排索引缓存(doc ID、term 等),另一种是字段数据缓存。可以通过增加缓存大小来提高 Elasticsearch 的性能。

然而,最佳实践同时也提醒:不要将缓存设置得太大,否则会占用过多内存。一般来说,最佳的实践是设定 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 中,并将其存储在同一索引中。这通常比单独对每个文档进行索引更快。例如:

在上述代码中,我们一次性加入了两个文档到 myindex 索引中。

需要注意的是,当使用 Bulk API 进行数据处理时,必须保持单个请求的大小在 100MB 左右。同时,也不要在单个文档中存储超过 Elasticsearch 节点的内存大小。

总结

本文介绍了 Elasticsearch 性能优化的一些重要坑位以及优化建议。在实际开发中,我们应该结合实际情况,合理配置分片/副本、heap 内存、缓存机制等各项参数。同时,我们也需要注意 Index Head 节点的使用,轻度复制机制的启用以及使用 Filter、Bulk API 等特性优化 Elasticsearch 的性能。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6469eb02968c7c53b09b2aca

纠错
反馈