Elasticsearch:提升 Elasticsearch 性能

1,077

Elasticsearch 是为你的用户提供无缝搜索体验的不可或缺的工具。 在最近的 QCon 会议上,我遇到了很多的开发者。在他们的系统中,Elastic Stack 是不可缺少的工具,无论在搜索,可观测性或安全领域,Elastic Stack 都发挥着巨大的作用。我们在手机中常见的应用或者网站上的搜索基本上有用 Elastic Stack 的影子。Elastic Stack 凭借其快速、准确和相关的搜索结果,它可以彻底改变用户与你的应用程序交互的方式。 但是,为确保你的 Elasticsearch 部署发挥最佳性能,监控关键指标并优化各种组件(如索引、缓存、查询和搜索以及存储)至关重要。 在这篇内容全面的博客中,我们将深入探讨调整 Elasticsearch 以最大限度发挥其潜力的最佳实践和技巧。 从优化集群健康、搜索性能和索引,到掌握缓存策略和存储选项,本博客涵盖了很多方面的内容。 无论你是经验丰富的 Elasticsearch 专家还是新手,遵循一些最佳实践以确保你的部署具有高性能、可靠和可扩展性都非常重要。

常用建议 

  • 使用正确的硬件:Elasticsearch 是一个内存密集型应用程序,因此使用具有足够 RAM 来处理数据的硬件非常重要。 此外,最好使用固态硬盘 (SSD) 进行存储,因为它们可以显着提高索引和搜索性能。
  • 规划你的索引策略:Elasticsearch 旨在处理大量数据,但重要的是要考虑这些数据是如何被索引的。 这包括你需要多少分片和副本、数据索引的频率以及如何处理更新和删除。请详细阅读 “Elasticsearch:我的 Elasticsearch 集群中应该有多少个分片?” 及 “Elasticsearch:如何部署 Elasticsearch 来满足自己的要求”。
  • 优化你的查询:Elasticsearch 是一个强大的搜索引擎,但重要的是要确保你的查询针对性能进行了优化。 这包括尽可能使用过滤器而不是查询,以及使用分页来限制返回的结果数量。
  • 让你的 Elasticsearch 版本保持最新:Elasticsearch 是一个活跃的项目,会定期发布新版本,其中包含错误修复和新功能。 务必使你的版本保持最新,以利用这些改进并避免任何已知问题。
  • 监控集群:Elasticsearch 提供了多种监控工具,例如 Elasticsearch Head 插件,可用于监控集群的健康状况和性能。 密切关注磁盘使用情况、CPU 和内存使用情况以及搜索请求的数量等内容非常重要。你可以参考 “Elastic:开发者上手指南” 中的 “监视及管理” 部分。

索引数据

  • 使用批量请求:Elasticsearch 的 bulk API 允许在单个 API 调用中执行多个索引/删除操作。 这显着提高了索引速度。 如果其中一个请求失败,则顶级错误标志设置为 true,错误详细信息将在相关请求下报告。
  • 使用多线程客户端索引数据:发送批量请求的单个线程将无法充分利用 Elasticsearch 集群的索引能力。 从多个线程或进程发送数据将有助于使用集群的所有资源,减少每次 fsync 的成本并提高性能。如果你是使用编程语言来实现数据写入,尽量采用 Elastic 官方所提供的丰富的客户端库来进行写入。它在设计中采用了很多的优化及对连接的管理。
  • 增加刷新间隔(index.refresh_interval):Elasticsearch 中默认的刷新间隔设置为 1 秒,但如果你的搜索流量很小,你可以增加这个值来优化索引速度。在实际的操作中,如果你在短时间里需要大量地写入数据,那么增加这个数值可以提高写入的速度。等数据写入完毕后,你再可以调整回来。
  • 减少 replica 数量:针对有些急需大量数据写入的情况,我们甚至可以把 replica 的数量设置为 0 以提高摄入数据的速度。等数据摄入完毕后,再对 replica 的值进行调整。如果你需要对摄入的过程有一个更为详细的了解,请参阅我的另外一篇文章 “Elasticsearch:彻底理解 Elasticsearch 数据操作”。
  • Use Auto-generated IDs:当使用显式 id 索引文档时,Elasticsearch 需要检查是否已经存在具有相同 id 的文档,这是一个代价高昂的操作。 使用自动生成的 ID 会跳过此检查,从而加快索引速度。
  • index.translog.sync_interval:此设置控制 translog 提交到磁盘的频率,与写操作无关。 默认值为 5s,但不允许小于 100ms 的值。
  • index.translog.flush_threshold_size:translog 存储尚未在 Lucene 中持久化,但如果分片停止则需要重放的操作。 此设置控制这些操作的最大总大小,防止恢复时间过长。
  • 避免大型文档:大型文档对网络、内存使用和磁盘造成压力,使索引速度变慢并影响邻近搜索和突出显示。
  • 显式设置映射:Elasticsearch 可以动态创建映射,但并不适用于所有场景。 显式设置映射将有助于确保最佳性能。
  • 避免嵌套类型:与父文档中的字段相比,对嵌套字段的查询速度较慢,并且检索匹配的嵌套字段也会进一步降低速度。关于 nested 数据类型,请阅读文章 “Elasticsearch:如何修改 nested 字段的值”。此外,目前 Kibana 针对 nested 数据没有支持。无法进行可视化。
  • 禁用“_all”字段:_all 字段将所有其他字段的值连接成一个字符串,需要更多的 CPU 和磁盘空间。 大多数用例不需要 _all 字段,你可以使用 copy_to 参数连接多个字段。 _all 字段在 Elasticsearch 6.0 及更高版本中默认禁用。

更多阅读:

查询及搜索

  • 如果可能,使用过滤器上下文而不是查询上下文:查询子句用于回答 “该文档与该子句的匹配程度如何?” 过滤子句用于回答 “该文档是否与该子句匹配?” Elasticsearch 只需要回答 “是” 或 “否”。 它不需要计算过滤子句的相关性分数,并且可以缓存过滤结果。请详细阅读 “Elasticsearch:深入理解 Elasticsearch 查询:过滤器查询 vs 全文搜索” 及 “Elasticsearch:cache 在 Elasticsearch 中的应用”。
  • 增加刷新间隔:增加刷新间隔有助于减少段数并降低搜索的 IO 成本。 并且,一旦发生刷新和数据更改,缓存将无效。 增加刷新间隔可以使 Elasticsearch 更有效地利用缓存。
  • 增加副本数:你拥有的副本越多,搜索中涉及的节点就越多。你可以阅读文章  “Elasticsearch:彻底理解 Elasticsearch 数据操作” 以了解更多关于搜索操作的流程。
  • 仅检索必要的字段:如果你的文档很大,而你只需要几个字段,请使用 stored_fields 来检索你需要的字段而不是所有字段。你可以阅读文章 “Elasticsearch:从搜索中获取选定的字段 fields” 以了解更多。
  • 避免通配符查询:通配符查询可能很慢并且占用大量资源。 最好尽可能避免使用它们。
  • 使用节点查询缓存:过滤器上下文中使用的查询结果缓存在节点查询缓存中,以便快速查找。
  • 使用分片查询缓存:你可以通过将 “index.requests.cache.enable” 设置为 true 来启用分片查询缓存。
  • 使用索引模板:索引模板可以帮助你自动将设置和映射应用于新索引。
  • 为每个索引配置至少一个副本:副本分片提供数据的冗余副本,并增加服务于读取请求(如搜索或检索文档)的能力。

更多阅读:

性能

  • Active shards 应该与 CPU 成正比:为了提高 write-heavy 用例的性能,刷新间隔应该增加到一个更大的值,例如 30s,并且应该增加 primary shards 以将写请求分配到不同的节点. 对于读取密集型用例,增加副本分片以平衡副本之间的查询/搜索请求会有所帮助。
  • 如果你的查询具有日期范围过滤器则按日期组织数据:对于日志记录或监控场景,按每日、每周或每月组织索引并获取指定日期范围的索引列表有助于提高性能。 Elasticsearch 只需要查询一个较小的数据集,而不是整个数据集,当数据过期时,很容易收缩/删除旧索引。
  • 如果你的查询具有筛选字段并且其值是可枚举的,则将你的数据拆分为多个索引:根据区域(例如,美国、欧元和其他)将索引拆分为多个较小的索引可以提高带有筛选子句的查询的性能 “地区”。
  • 确保使用 “索引” 和 “查询和搜索”部分中的最佳实践。请参考上面的部分。

扩展

  • 如果你的查询具有日期范围过滤器,则按日期组织数据:对于大多数日志记录或监控场景,按每日、每周或每月组织索引并获取指定日期范围的索引列表有助于提高性能。 Elasticsearch 只需要查询一个较小的数据集,而不是整个数据集,当数据过期时,很容易收缩/删除旧索引。
  • 索引状态管理:定义自定义管理策略以自动执行日常任务并将其应用于索引和索引模式。 例如,可以定义一个策略,在 30 天后将索引移至只读状态,然后在 90 天后将其删除。
  • 使用 Curator 旋转数据:Curator 可以使用其众多过滤器帮助识别满足特定条件的索引和快照,例如 60 多天前创建的索引或未能完成的快照。

Elastic Stack 里含有索引生命周期管理。它可以帮我们自动管理索引的生命周期,一旦设定策略。请详细阅读文章 “Elastic:开发者上手指南” 中的 “生命周期管理(ILM)” 章节。

监控

为了监控 Elasticsearch 集群的性能并检测任何潜在问题,你应该定期跟踪以下指标:

  • Cluster Health Nodes and Shards:监控集群中的节点数量,以及分片数量及其分布。
  • 搜索性能:请求延迟和速率 - 跟踪搜索请求的延迟和每秒搜索请求的数量。
  • 索引性能:刷新时间和合并时间 - 监控刷新索引所需的时间和合并段所需的时间。
  • Node Utilization: Thread Pools - 监控每个节点上线程池的使用情况,例如索引池

 请详细阅读 “Elastic:开发者上手指南” 中的 “监视及管理” 部分

通过遵循这些最佳实践,你可以确保你的 Elasticsearch 部署具有高性能、可靠性和可扩展性。 请记住,Elasticsearch 是一个强大的搜索和分析引擎,可以快速且近乎实时地处理大量数据,但重要的是要规划、优化和监控你的部署以充分利用它。