Elasticsearch 集群典型报错日志"逆向"分析

开发 前端
通过合理配置和优化,Elasticsearch 集群的性能问题是可以逐步解决的。但,爆改集群默认配置是不建议的。关键在于合理分配资源,优化查询和索引操作,同时结合监控工具和日志分析,及时发现并解决潜在问题。

1、集群环境及存在问题

1.1 集群环境

  • 1 台宿主机,2 个 ES 节点。
  • 宿主机配置:56 核 CPU, 256G 内存,普通非SSD 磁盘
  • 宿主机除了部署 ES 集群两个节点,还部署了其他服务如 redis、其他(不详)。

1.2 索引分片

  • 单索引 700 GB 左右。
  • 20 个分片。

1.3 改动过如下配置

图片图片

1.4 存在问题

Elasticsearch 查询特别慢,内存使用率 93%, 现在没什么解决思路。

————问题来自球友:https://t.zsxq.com/LcRV0

2、仅如上信息,可以发现的问题

2.1 存在典型问题

两节点分布在一台机器,还有混部了一些其他的服务。

本质是两虚拟机共享一个实体服务器。

混合部署了 Redis 等服务,这是大问题。

Redis 属于内存数据库,“吃内存”厉害。我们一般不建议这么搞,官方也不建议这么搞。

2.2 盲目修改集群配置,可能带来潜在风险

其中,search.max_buckets 默认值:10000。现在扩大了1000倍,改成了 1000 万。

该配置项用于限制 Elasticsearch 中聚合查询(如 histogram 聚合)中返回的最大桶数。过高的桶数可能会导致内存使用过多,影响集群性能。

其中,thread_pool.write.queue_size 默认值:200。现在改成 2048,扩大了 10 倍+。

该配置项用于指定写入操作的线程池队列大小,当队列满时,新的写入请求将被拒绝。

增大队列大小可以缓解写入压力,但也会增加内存消耗。其中,indices.fielddata.cache.size 默认值:未设置具体默认值(动态分配),

该配置项用于限制字段数据缓存的大小,默认情况下是根据 JVM 堆内存动态调整。可以使用百分比表示,例如 20% 表示使用最大可用堆内存的 20% 作为缓存。

也就是这个支持动态调整的,咱们给写死了。

上述修改其实都经不起推敲和验证,非常的“大胆”,但出问题往往也会超出咱们的预期。

2.2 其他问题不明显

  • 疑似问题1:单索引是700g左右, 分片20?单分片大小35g,具体单文档细节不详。
  • 疑似问题2:只有2台机器。本质两台机器角色都具备:主节点、数据节点角色,其中一台还充当协调节点角色。
  • 疑似问题3:症状提及的查询慢问题,需要给出慢查询日志,需要给出监控指标数据,需要描述一下业务,需要给出检索的DSL语句。

3、拿到集群日志,一切变得明朗

图片图片

如上截图为两个节点的日志,-02-1 为主节点日志,-02-2 为另外一个节点的日志。

4、主节点日志“逆向”分析

4.1 test-1016-2024-08-02-1.log 日志含拒绝请求“9790”次

从最早日期:[2024-08-02T17:15:54,487

到最晚日期:[2024-08-02T17:28:57,460]

累计时长:13 分 2.973 秒。

共有如下类似相同报错:9790 次。

日志截取如下:

Caused by: org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.common.util.concurrent.TimedRunnable@5ccc5247 on QueueResizingEsThreadPoolExecutor[name = slav1/search, queue capacity = 1000, min queue capacity = 1000, max queue capacity = 1000, frame size = 2000, targeted response rate = 1s, task execution EWMA = 12.2ms, adjustment amount = 50, org.elasticsearch.common.util.concurrent.QueueResizingEsThreadPoolExecutor@10c62020[Running, pool size = 85, active threads = 85, queued tasks = 1000, completed tasks = 370806]]

也就是说,当前节点已经高负荷扛不住了。

图片图片

上述错误是由于 Elasticsearch 线程池饱和导致的。这具体表现在 EsRejectedExecutionException 中,表示有任务被拒绝执行。

详细原因拆解如下:

  • QueueResizingEsThreadPoolExecutor 饱和

报错信息显示 search 线程池的队列已经达到最大容量(queue capacity = 1000),并且活动线程数已经达到最大(active threads = 85),所以新任务被拒绝执行。

  • 任务积压

报错信息中提到有 1000 个任务在队列中等待执行,说明当前系统的负载很高,可能是因为查询请求过多或请求处理时间较长。

  • 搜索请求过多或复杂

从报错信息看,搜索请求的参数和查询条件比较复杂(包含多重布尔查询、排序等,见 4.2 的 DSL 语句),这可能导致了较高的计算和处理时间。

可能的解决方案探讨:

  • 方案1:增加节点资源

增加 Elasticsearch 集群中的节点数,或者增加现有节点的资源(CPU、内存等),以分担负载。

看老板给不给硬件投入支持。

  • 方案2:优化查询

简化查询条件,减少不必要的字段返回和高亮显示等操作,尽量优化查询性能。见4.2 章节分析。

  • 方案3:调整线程池设置

调整 search 线程池的配置,如增大 queue capacity 和 pool size,以便处理更多的并发请求。

但前提:必须结合硬件资源进行合理调整,而不是盲改 100倍、1000倍甚至更大的值。

4.2 打开slow_log 慢日志后,DSL语句显现。

Elasticsearch 日志能否把全部请求打印出来?

图片图片

4.2.1 问题1:"track_total_hits": 2147483647

问题描述:将 track_total_hits 设置为 2147483647(即 2^31-1)是非常高的一个值,会导致性能问题。

  • 原因:

(1)性能消耗大。

计算所有匹配文档的总数需要遍历所有匹配的文档,这对于大规模数据集来说是非常耗时和耗资源的操作。

(2)不必要的精确度。

通常用户并不需要一个如此精确的匹配数量,大部分情况下一个较小的估算值已经足够。

Elasticsearch 8.X 聚合查询下的精度问题及其解决方案

  • 推荐优化后的解决方案:

(1)合理设置 track_total_hits

将 track_total_hits 设置为 true 或者一个合理的数值,例如 10000,以满足大多数统计需求,同时减少系统负担。

(2)分页处理

通过分页获取数据,而不是一次性获取大量匹配文档的总数。

干货 | 全方位深度解读 Elasticsearch 分页查询

4.2.2  问题2:基于脚本排序

问题描述:脚本排序会极大地影响查询性能,尤其是在处理大量数据时。

原因:

  • (1)计算开销大

脚本排序需要在每个匹配的文档上执行脚本计算,这会导致高额的 CPU 开销。

  • (2)缓存难以利用

脚本排序结果难以缓存,因为每次请求可能都会涉及不同的计算逻辑和参数。

  • 推荐解决方案

(1)预计算字段

尽量将排序逻辑预计算成字段,存储在文档中,避免在查询时实时计算。

例如,预先计算并存储评分、排名等,可以借助 ingest pipeline 预处理实现。

这就是咱们之前多次强调过的“空间换时间”。

Elasticsearch的ETL利器——Ingest节点

Elasticsearch 预处理没有奇技淫巧,请先用好这一招!

(2)优化脚本

如果必须使用脚本排序,确保脚本尽可能简单和高效。使用 Painless 脚本语言并确保脚本已编译优化。最好别用!

(3)索引优化

使用合适的索引结构和字段类型,确保查询性能和排序效率。

4.2.3 问题3:Mapping 中有超级多字段,仅 includes 就有:41 个 字段。

Mapping 中包含过多字段,尤其是查询时 _source 包含大量字段,会增加查询负担。

原因:

(1)I/O 开销大

每次查询需要从磁盘读取大量字段数据,增加了 I/O 开销。

(2)网络传输慢

返回的数据量大,增加了网络传输时间,影响响应速度。

(3)内存消耗大

在返回大量字段数据(41个字段的数据)时,会占用较多内存,影响系统性能。

  • 建议解决方案:

(1)按需返回字段

仅在 _source 中包含必要的字段,减少数据量。例如,只包含用户实际需要显示或处理的字段。

(2)字段分类管理

将常用字段和不常用字段分开管理,常用字段可以集中存储和索引,不常用字段可以进行更高效的压缩和存储。

Elasticsearch 8.x 存储有无压缩?能压缩到多少?

(3)动态字段处理

考虑使用动态字段(借助运行时字段实现)或字段别名,在需要时动态扩展,而不是在 Mapping 中预先定义所有可能的字段。

4.3 No search context found for id [XXXXXXX],报错:236次。

如下错误:

org.elasticsearch.search.SearchContextMissingException: No search context found for id [208049],

在 13 分 2.973 秒内共发生 236 次。

图片图片

这表明在执行 Scroll 查询时,某些查询上下文已经丢失或超时。

[2024-08-02T12:05:44,520][DEBUG][o.e.a.s.TransportSearchScrollAction] [slave] [208049] Failed to execute query phase
org.elasticsearch.transport.RemoteTransportException: [slav1][172.17.0.1:29302][indices:data/read/search[phase/query/scroll]]
Caused by: org.elasticsearch.search.SearchContextMissingException: No search context found for id [208049]

4.3.1 “上下文丢失”可能的原因分析

  • 查询上下文过期 Scroll 查询上下文默认在保持不活动状态下只会持续一段时间(默认 1 分钟)。如果查询处理时间超过此时间,上下文会被清除,从而导致此错误。
  • 高并发导致上下文管理混乱 在高并发场景下,大量 Scroll 查询请求可能导致系统无法及时管理和维护这些上下文,造成上下文丢失。
  • 节点重启或崩溃 执行 Scroll 查询的节点如果在查询过程中重启或崩溃,会导致查询上下文丢失。

4.3.2 解决方案

  • 方案1:增加 Scroll 上下文的保持时间

需要排查咱们做了啥?

在 Scroll 查询请求中增加 scroll 参数,例如设置为 5 分钟:

{
  "scroll": "5m"
}

根据查询复杂度和数据量调整保持时间,确保足够长的时间完成查询。

如果数据量不大或可以分段处理,使用常规分页查询代替 Scroll 查询,减少对上下文的依赖。

  • 方案二:优化查询性能 简化查询条件,减少不必要的计算,提升查询速度。

如前所述,“空间换时间”,预先计算和缓存部分查询结果,减少实时计算量。

5、非主节点日志“逆向分析”

除了类似主节点报错外,非主节点报错如下:

[2024-08-02T17:41:21,517][WARN 


org.elasticsearch.cluster.block.ClusterBlockException: blocked by: [SERVICE_UNAVAILABLE/2/no master];

图片图片

大致推测:[2024-08-02T17:41:21,517]  主节点宕机了。

5.1 问题描述

上述日志报错表明 Elasticsearch 集群当前没有主节点(master node)。

在 Elasticsearch 集群中,主节点负责管理集群状态和元数据(例如索引和节点信息)。如果集群中没有主节点,整个集群会变得不可用,导致无法执行任何操作,包括索引和查询。

5.2 原因猜测

  • 主节点故障:当前主节点可能已经发生故障或崩溃(猜测就是第4部分分析的,扛不住压力导致宕机)。
  • 资源不足:主节点所在的物理机器资源不足(如内存、CPU),导致主节点崩溃。

6、小结

通过合理配置和优化,Elasticsearch 集群的性能问题是可以逐步解决的。

但,爆改集群默认配置是不建议的。

关键在于合理分配资源,优化查询和索引操作,同时结合监控工具和日志分析,及时发现并解决潜在问题。

希望上述分析和建议能够帮助大家更好地管理和优化 Elasticsearch 集群,提高系统的稳定性和响应速度。

第一部分提到的集群配置、节点角色划分、分片大小、文档大小、文档映射、检索语句、监控指标等都值得进一步深入探讨......

责任编辑:武晓燕 来源: 铭毅天下Elasticsearch
相关推荐

2023-11-28 18:03:01

SQLUDF

2022-10-20 10:37:44

2010-09-30 09:40:45

2020-04-09 11:56:10

Elasticsear集群硬件

2015-08-21 17:52:52

逆向分析BinNavi

2024-01-30 17:37:50

es集群数据

2009-03-26 10:12:00

WCDMA网络建设

2011-08-10 10:39:47

路由器路由器故障

2021-08-10 07:27:42

Elasticsear集群开源

2022-02-17 08:53:38

ElasticSea集群部署

2023-11-29 08:35:28

群多租户ES运维

2022-01-03 07:49:04

Kubernetes集群容器

2024-03-26 10:13:54

日志引擎SigLens

2018-08-20 13:46:59

Android逆向分析终端安全

2015-07-30 15:24:21

Micro-PaaSKubernetes技术入门

2021-07-20 08:00:00

集群Elasticsear工具

2015-08-03 15:48:22

Linux日志

2011-11-21 15:35:49

日志分析

2017-02-14 08:36:56

2015-01-09 16:32:25

点赞
收藏

51CTO技术栈公众号