【Elastic Engineering】Elasticsearch:管理 Elasticsearch 内存并进行故障排除

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch:管理 Elasticsearch 内存并进行故障排除

作者:刘晓国


随着 Elastic 扩展我们的 Elasticsearch Service Cloud 产品和自动上线,我们已经将 Elastic Stack 的受众范围从完整的运营团队扩展到了数据工程师,安全团队和顾问。作为 Elastic 支持团队的代表,我喜欢与更多用户背景甚至更广泛的用例进行交互。

在更广泛的听众中,我看到了更多有关管理资源分配的问题,尤其是神秘的 shard 堆比率和避免使用熔断器(circuit breaker)的问题。我完全理解!当我开始使用 Elastic Stack 时,我遇到了同样的问题。这是我关于 Java 堆和时间序列数据库分片以及扩展自己的基础结构的第一个介绍。

当我加入 Elastic 团队时,我很喜欢文档之外的内容,我们有博客和教程,因此我可以很快上手。但是后来我在第一个月就非常费劲地使我的理论知识与用户通过我的问题队列发送的错误相关联。最终,我发现像其他支持团队成员一样,许多报告的错误仅是分配问题的征兆,而相同的七个链接(在下面的理论部分可以看到)会带给用户加快成功管理其资源分配的速度。

作为支持团队的代表,在以下各节中,我将遍历我们向用户发送的最重要的分配管理理论链接,我们看到的最重要的症状以及我们指导用户更新其配置以解决其资源分配问题的地方。


理论


作为 Java 应用程序,Elasticsearch 需要从系统的物理内存中分配一些逻辑内存(堆)。 这应该最多是物理 RAM 的一半,上限为 32GB。 设置更高的堆使用率通常是为了响应昂贵的查询和更大的数据存储。 父级熔断器默认为95%,但是一旦持续达到85%,我们建议你扩展资源。

Elasticsearch包 含多个熔断器,这些熔断器用于防止操作引起 OutOfMemoryError。 每个断路器都指定了可以使用多少内存的限制。 此外,还有一个父级熔断器,用于指定可在所有断路器上使用的内存总量。

我强烈建议我们的团队提供这些概述文章,以获取更多信息:


配置


开箱即用,Elasticsearch 的默认设置会根据节点角色和总内存自动调整 JVM 堆的大小。 但是,根据需要,你可以通过以下三种方式直接对其进行配置:

1.直接在本地 Elasticsearch 文件的 config > jvm.options 文件中


1. ## JVM configuration 
2. ################################################################ 
3. ## IMPORTANT: JVM heap size 
4. ################################################################ 
5. … 
6. # Xms represents the initial size of total heap space 
7. # Xmx represents the maximum size of total heap space 
8. -Xms4g
9. -Xmx4g


2. 作为 docker-compose 中的 Elasticsearch 环境变量


1. version: '2.2'
2. services:
3.   es01:
4.     image: docker.elastic.co/elasticsearch/elasticsearch:7.12.0
5.     environment:
6.       - node.name=es01
7.       - cluster.name=es
8.       - bootstrap.memory_lock=true
9.       - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
10.       - discovery.type=single-node
11.     ulimits:
12.       memlock:
13.         soft: -1
14.         hard: -1
15.     ports:
16.       - 9200:9200


3.通过我们的 Elasticsearch Service > Deployment > Edit view。 注意:滑动条分配物理内存,大约一半将分配给堆。


image.png


故障排除


如果您的群集当前遇到性能问题,则很可能归咎于通常的怀疑

  • 配置问题:分片,没有 ILM 策略
  • 引入的高体量:高请求速度/负载,重叠昂贵的查询/写入

所有以下所有 cURL / API请求都可以在 Elasticsearch Service > API 控制台中作为 Elasticsearch API 的 cURL 发出,或者在 Kibana> Dev Tools 下进行。


过度分片


数据索引存储在 sub-shards 中,这些 sub-shards 使用堆进行维护以及在搜索/写入请求期间使用。 shard 大小应限制为 50GB,数量应限制为通过以下公式确定的值:

shards <= sum(nodes.max_heap) * 20

以上面的 Elasticsearch Service 为例,在两个区域中具有 8GB 的物理内存(这将总共分配两个节点)

1. # node.max_heap 
2. 8GB of physical memory / 2 = 4GB of heap  
3. # sum(nodes.max_heap) 
4. 4GB of heap * 2 nodes = 8GB 
5. # max shards 
6. 8GB * 20
7. 160

然后将其与 _cat /allocation 进行交叉比较

1. GET /_cat/allocation?v=true&h=shards,node
2. shards node
3. 41 instance-0000000001
4. 41 instance-0000000000

或者使用 _cluster/health

1. GET /_cluster/health?filter_path=status,*_shards
2. {
3. "status": "green",
4. "unassigned_shards": 0,
5. "initializing_shards": 0,
6. "active_primary_shards": 41,
7. "relocating_shards": 0,
8. "active_shards": 82,
9. "delayed_unassigned_shards": 0
10. }

因此,此部署具有最多160个建议的82个分片。 如果计数高于建议值,则可能在接下来的两个部分中出现症状(请参阅下文)。

如果有任何 shard 报告(除 active_shards 或 active_primary_shards)之外的数字 > 0,则表明你已确定导致性能问题的主要原因。

最常见的情况是,如果报告了问题,则其值为 unassigned_shards > 0。 如果这些 shard 是主要分片,则群集将报告为状态:红色;如果仅副本,它将报告为状态:黄色。 (这就是在索引上设置副本很重要的原因,这样,如果群集遇到问题,它可以恢复而不是遭受数据丢失。)

假设我们有一个状态:黄色,带有一个未分配的分片。 为了进行调查,我们将通过 _cat /shards 来查看哪个索引分片遇到问题

1. GET _cat/shards?v=true&s=state
2. index                                     shard prirep state        docs   store ip           node
3. logs                                      0     p      STARTED         2  10.1kb 10.42.255.40 instance-0000000001
4. logs                                      0     r      UNASSIGNED
5. kibana_sample_data_logs                   0     p      STARTED     14074  10.6mb 10.42.255.40 instance-0000000001
6. .kibana_1                                 0     p      STARTED      2261   3.8mb 10.42.255.40 instance-0000000001

因此,这将用于我们的非系统索引日志,该日志具有未分配的副本分片。 让我们看看通过运行 _cluster/allocation/explain 是什么造成这个原因(专业提示:当你向我们发送问题以提供支持时,这正是我们的工作)

1. GET _cluster/allocation/explain?pretty&filter_path=index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*
2. { "index": "logs",
3. "node_allocation_decisions": [{
4. "node_name": "instance-0000000005",
5. "deciders": [{
6. "decider": "data_tier",
7. "decision": "NO",
8. "explanation": "node does not match any index setting

此错误消息指向 data_hot,它是索引生命周期管理(ILM)策略的一部分,并指示我们的 ILM 策略与我们当前的索引设置不一致。 在这种情况下,此错误的原因是由于没有指定 hot-warm 节点而设置了 hot-warm ILM 策略。

仅供参考,如果你在没有任何 unsigned shards 的情况下运行此命令,则会出现 400 错误,提示找不到任何未分配的分片进行解释,因为没有错误要报告。

如果你遇到非逻辑原因(例如,临时网络错误,例如分配期间节点离开群集),则可以使用 Elastic 方便的 _cluster/reroute。

POST /_cluster/reroute

无需定制的此请求将启动一个异步后台进程,该进程尝试分配所有当前状态:UNASSIGNED shards。


熔断器


最大化堆分配会导致对集群的请求超时或错误,并且经常会导致集群遇到熔断器异常。 熔断器会导致类似的 elasticsearch.log 事件:

Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [] would be [num/numGB], which is larger than the limit of [num/numGB], usages [request=0/0b, fielddata=num/numKB, in_flight_requests=num/numGB, accounting=num/numGB]

要进行调查,请查看你的 heap.percent,方法是查看 _cat/nodes:

1. GET /_cat/nodes?v=true&h=name,node*,heap*
2. # heap = JVM (logical memory reserved for heap)
3. # ram  = physical memory
4. name                                node.role heap.current heap.percent heap.max
5. tiebreaker-0000000002 mv             119.8mb           23    508mb
6. instance-0000000001   himrst           1.8gb           48    3.9gb
7. instance-0000000000   himrst           2.8gb           73    3.9gb

或者,如果你先前已启用它,请导航至 Kibana > Stack Monitoring。

image.png

如果你确定正被击中内存熔断器,则可以考虑暂时增加堆容量,为自己腾出空间进行调查。 在调查根本原因时,请通过群集代理日志或 elasticsearch.log 查找先前的连续事件。 你将寻找

  • 昂贵的查询,尤其是:
  • 高桶聚合
  •  当我发现搜索在根据搜索大小或存储桶尺寸运行查询之前临时分配堆的某个端口时,我感到非常傻,因此设置 10,000,000 确实让我的运营团队感到非常沮丧。
  • 非优化映射
  • 感到愚蠢的第二个原因是,当我认为进行分层报告会比扁平化的数据更好(不是)。
  • 请求量/速度:通常是批量或异步查询


是时间该扩容


如果这不是你第一次接触熔断器,或者你怀疑这将是一个持续存在的问题(例如,持续击中85%,那么该是时候考虑扩展资源了),那么你需要仔细研究一下 JVM 内存压力作为你的长期堆指标。 你可以在 Elasticsearch Service > Deployment 中进行检查

image.png

或者你可以根据 _nodes/stats 信息进行计算:

1. GET /_nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
2. {"nodes": { "node_id": { "jvm": { "mem": { "pools": { "old": {
3. "max_in_bytes": 532676608,
4. "peak_max_in_bytes": 532676608,
5. "peak_used_in_bytes": 104465408,
6. "used_in_bytes": 104465408
7. }}}}}}}

这里:

JVM Memory Pressure = used_in_bytes / max_in_bytes

潜在的症状是 elasticsearch.log 中的垃圾收集器(gc)事件发生的频率高且持续时间长

[timestamp_short_interval_from_last][INFO ][o.e.m.j.JvmGcMonitorService] [node_id] [gc][number] overhead, spent [21s] collecting in the last [40s]

如果你确认了这种情况,则需要研究扩展集群或减少达到集群的需求。 你需要调查/考虑:

  • 增加堆资源(堆/节点,节点数)
  • 减少分片(删除不必要的/旧的数据,使用 ILM 将数据放入温/冷存储中,以便你可以缩小数据,关闭不需要的数据的副本,以防丢失)


结论


喔! 从我在 Elastic Support 中看到的情况来看,这是最常见的用户问题的缩影:未分配的分片 (unassigned shards),不平衡的分片堆,熔断器,大量垃圾收集和分配错误。 所有这些都是核心资源分配管理对话的症状。 希望你现在也了解理论和解决步骤。

不过,如果你现在仍无法解决问题,请随时与我们联系。 我们在这里,乐意为你服务! 你可以通过 Elastic DiscussElastic Community Slack 咨询,培训和支持与我们联系。

为我们将 Elastic Stack 的资源分配作为非运维(也喜欢运维)进行自管的能力感到高兴!


参考:

【1】https://www.elastic.co/blog/managing-and-troubleshooting-elasticsearch-memory

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
存储 监控 搜索推荐
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——安装篇(一)
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——安装篇(一)
|
4月前
|
存储 消息中间件 缓存
读Flink源码谈设计:有效管理内存之道
在最初接触到Flink时,是来自于业界里一些头部玩家的分享——大家会用其来处理海量数据。在这种场景下,`如何避免JVM GC带来StopTheWorld带来的副作用`这样的问题一直盘绕在我心头。直到用了Flink以后,阅读了相关的源码(以1.14.0为基准),终于有了一些答案。在这篇文章里也是会分享给大家。
541 1
|
6月前
|
程序员 C语言 C++
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(下)
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(下)
24 0
|
6月前
|
程序员 编译器 C语言
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(上)
动态内存管理函数的使用与优化技巧(内存函数、柔性数组)(上)
32 0
|
4月前
|
安全 大数据 API
elasticsearch|大数据|elasticsearch的api部分实战操作以及用户和密码的管理
elasticsearch|大数据|elasticsearch的api部分实战操作以及用户和密码的管理
63 0
|
16天前
|
存储 缓存 监控
Linux内存和硬盘空间管理技巧
了解Linux内存和硬盘管理技巧,提升系统性能和稳定性。使用`free`, `top`, `vmstat`监控内存,通过`sync`, `echo 1 &gt; /proc/sys/vm/drop_caches`清理缓存。利用Swap分区释放内存。借助`df`, `du`检查硬盘空间,清理无用文件,使用`clean-old`, `gzip`, `tar`压缩归档。查找大文件用`find`和`du`,确保
33 0
|
1月前
|
存储 算法 Java
如何使用 Python 管理内存和避免内存泄漏?
如何使用 Python 管理内存和避免内存泄漏?
100 35
|
2月前
|
存储 缓存 自然语言处理
【Elasticsearch专栏 04】深入探索:Elasticsearch倒排索引中的词条是如何存储和管理
倒排索引中,词条以有序方式存储在词典中,关联倒排列表,记录文档ID和位置信息。词条的添加涉及分词、添加到词典和更新倒排列表。删除涉及从词典和倒排列表中移除词条。查询时,快速定位词条,获取倒排列表以定位相关文档。整个过程涉及高效的数据结构和优化策略。
|
2月前
|
缓存 Java API
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——聚合与搜索(三)
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——聚合与搜索(三)
|
2月前
|
存储 Java API
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧———索引与数据上传(二)
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧———索引与数据上传(二)

相关产品

  • 检索分析服务 Elasticsearch版