Elasticsearch性能优化指南:线程池优化详细介绍

文摘   2024-10-13 09:00   辽宁  
关注下方公众号,获取更多热点资讯

提升性能:Elasticsearch 线程池的详细介绍

Elasticsearch使用多个线程池(thread pool)来管理内存消耗和处理并发请求。这些线程池负责不同类型的任务,通过线程和队列的配置来平衡系统的资源使用和性能。在队列中,挂起的请求可以暂时被保存而不是直接丢弃,从而减少因系统资源不足而导致的请求失败。

文章详细介绍了各类线程池的配置方法及其对应的场景,通过优化线程池,特别是在高并发环境下,能够减少请求失败,提升整体系统的稳定性和响应速度。


1. 线程池概述

线程池是Elasticsearch中用于处理不同类型任务的核心机制。每个节点都有多个线程池,负责处理不同类型的操作。这些线程池的类型和配置可以显著影响Elasticsearch集群的性能和资源使用。

主要线程池概述

  • • Generic 线程池:用于处理通用的后台任务,如节点发现等操作,具备动态扩展能力。

  • • Index 线程池:负责文档的索引和删除操作,配置固定数量的线程。

  • • Search 线程池:专门处理搜索、计数和建议操作,确保高效的搜索性能。

  • • Get 线程池:用于处理单个文档的获取请求,处理高频查询操作。

  • • Bulk 线程池:处理批量索引、更新和删除请求,优化批量操作的并发处理。

  • • Snapshot 线程池:用于创建和恢复快照操作,具备动态调整线程数的能力。

  • • Warmer 线程池:负责分段预热操作,确保新分段在被查询前已准备就绪。

  • • Refresh 线程池:执行索引刷新操作,将新数据从内存持久化到磁盘。

  • • Listener 线程池:用于 Java 客户端异步操作监听,确保监听操作独立于主线程池执行。

1.1 线程池的作用

Elasticsearch中的每个线程池都有其特定的用途,例如:

  • • Generic 线程池负责后台操作,例如节点发现、定时任务。

  • • Search 线程池主要用于搜索、建议等操作。

  • • Write 线程池用于处理索引、删除、更新文档等操作。

合理配置这些线程池能够有效管理系统资源并优化性能。


2. 线程池的详细介绍

Elasticsearch中的线程池在处理并发操作、优化资源使用和提高性能方面起着至关重要的作用。下面将详细介绍 genericindexsearchgetbulksnapshotwarmerrefresh 和 listener 这些常见线程池的用途和配置。

说明: ${node.processors} 为 node.processors: 2 设置的值。

系统会自动检测处理器的数量,并基于它自动设置线程池设置。在某些情况下,覆盖检测到的处理器数量可能很有用。这可以通过显式设置 node.processors 设置来完成。

查看配置方法

GET _nodes/thread_pool

generic线程池

  • • 用途:用于通用操作,如后台节点发现、一些周期性任务等。

  • • 线程池类型scaling

  • • 说明:线程数可以根据需求动态扩展。

配置方法

elasticsearch.yml配置文件中添加以下内容:

thread_pool.generic.type: scaling
thread_pool.generic.core: 4
thread_pool.generic.max: 128
thread_pool.generic.keep_alive: 30s

search线程池

  • • 用途:用于处理搜索、计数、推荐等操作。

  • • 线程池类型fixed_auto_queue_size

  • • 大小int((${node.processors} * 3) / 2) + 1

  • • 初始队列大小:1000

  • • 说明:该线程池的大小默认是根据系统处理器的数量自动计算的。

配置方法

thread_pool.search.type: fixed_auto_queue_size
thread_pool.search.size: 13
thread_pool.search.queue_size: 1000

search_throttled线程池

  • • 用途:用于处理搜索受限索引上的操作,如count/search/suggest/get

  • • 线程池类型fixed_auto_queue_size

  • • 大小:1

  • • 初始队列大小:100

  • • 说明:由于受限索引通常不会有大量的并发操作,因此此线程池配置为单线程。

配置方法

thread_pool.search_throttled.type: fixed_auto_queue_size
thread_pool.search_throttled.size: 1
thread_pool.search_throttled.queue_size: 100

get线程池

  • • 用途:处理获取文档的操作。

  • • 线程池类型fixed

  • • 大小:等于分配的处理器数。

  • • 队列大小:1000

  • • 说明:此线程池用于检索单个文档的操作。

配置方法

thread_pool.get.type: fixed
thread_pool.get.size: 8
thread_pool.get.queue_size: 1000

analyze线程池

  • • 用途:用于分析请求,如文本分词和分析操作。

  • • 线程池类型fixed

  • • 大小:1

  • • 队列大小:16

  • • 说明:分析操作通常是短期操作,因此此线程池的配置较小。

配置方法

thread_pool.analyze.type: fixed
thread_pool.analyze.size: 1
thread_pool.analyze.queue_size: 16

write线程池

  • • 用途:用于处理单文档索引、删除、更新以及批量请求。

  • • 线程池类型fixed

  • • 大小:等于分配的处理器数。

  • • 队列大小:10000

  • • 说明:此线程池负责所有与写入相关的操作,队列较大,以处理潜在的大量写入请求。

配置方法

thread_pool.write.type: fixed
thread_pool.write.size: 8
thread_pool.write.queue_size: 10000

snapshot线程池

  • • 用途:用于快照和恢复操作。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小min(5, (${node.processors}) / 2)

  • • 说明:快照和恢复操作通常是后台操作,因此使用扩展线程池来根据负载动态调整。

配置方法

thread_pool.snapshot.type: scaling
thread_pool.snapshot.keep_alive: 5m
thread_pool.snapshot.max: 4

snapshot_meta线程池

  • • 用途:用于快照库元数据的读取操作。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小min(50, (${node.processors} * 3))

配置方法

thread_pool.snapshot_meta.type: scaling
thread_pool.snapshot_meta.keep_alive: 5m
thread_pool.snapshot_meta.max: 50

warmer线程池

  • • 用途:用于段预热操作。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小min(5, (${node.processors}) / 2)

  • • 说明:当新段写入时,Elasticsearch通过预热操作优化性能。

配置方法

thread_pool.warmer.type: scaling
thread_pool.warmer.keep_alive: 5m
thread_pool.warmer.max: 4

refresh线程池

  • • 用途:用于刷新操作,确保数据能够及时搜索到。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小min(10, (${node.processors}) / 2)

  • • 说明:刷新操作可以在后台执行,并随着负载的变化进行扩展。

配置方法

thread_pool.refresh.type: scaling
thread_pool.refresh.keep_alive: 5m
thread_pool.refresh.max: 6

listener线程池

  • • 用途:主要用于Java客户端在监听器设置为true时执行操作。

  • • 线程池类型scaling

  • • 最大线程池大小min(10, (${node.processors}) / 2)

  • • 说明:此线程池处理来自客户端的操作监听,确保操作结果能够及时返回给客户端。

配置方法

thread_pool.listener.type: scaling
thread_pool.listener.max: 6

fetch_shard_started线程池

  • • 用途:用于列出分片状态。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小:2 * 分配的处理器数。

  • • 说明:用于处理分片恢复过程中列出分片状态的操作。

配置方法

thread_pool.fetch_shard_started.type: scaling
thread_pool.fetch

_shard_started.keep_alive: 5m
thread_pool.fetch_shard_started.max: 16

fetch_shard_store线程池

  • • 用途:用于处理分片存储列表操作。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小:2 * 分配的处理器数。

  • • 说明:处理从分片存储中获取数据的操作。

配置方法

thread_pool.fetch_shard_store.type: scaling
thread_pool.fetch_shard_store.keep_alive: 5m
thread_pool.fetch_shard_store.max: 16

flush线程池

  • • 用途:用于定期将内存中的数据写入磁盘。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小min(10, (${node.processors}))

  • • 说明:定期刷新操作确保Elasticsearch的数据一致性与持久性。

配置方法

thread_pool.flush.type: scaling
thread_pool.flush.keep_alive: 5m
thread_pool.flush.max: 10

force_merge线程池

  • • 用途:用于段合并操作。

  • • 线程池类型fixed

  • • 大小:1

  • • 队列大小Integer.MAX_VALUE

  • • 说明:段合并是资源密集型操作,因此强制合并操作被限制为单线程。

配置方法

thread_pool.force_merge.type: fixed
thread_pool.force_merge.size: 1
thread_pool.force_merge.queue_size: -1

management线程池

  • • 用途:处理集群的后台管理任务,如集群状态更新。

  • • 线程池类型scaling

  • • 最大线程池大小:5

  • • 说明:用于处理集群管理任务,确保集群状态和任务分发的稳定性。

配置方法

thread_pool.management.type: scaling
thread_pool.management.max: 5

system_read线程池

  • • 用途:用于处理系统级别的读取请求。

  • • 线程池类型fixed_auto_queue_size

  • • 大小:2

  • • 说明:专门为系统级别的读取操作优化,队列大小根据负载动态调整。

配置方法

thread_pool.system_read.type: fixed_auto_queue_size
thread_pool.system_read.size: 2

system_write线程池

  • • 用途:用于处理系统级别的写入请求。

  • • 线程池类型fixed_auto_queue_size

  • • 大小:2

  • • 说明:类似system_read,专注于处理系统写入操作。

配置方法

thread_pool.system_write.type: fixed_auto_queue_size
thread_pool.system_write.size: 2

system_critical_read线程池

  • • 用途:处理关键的系统级别读取操作。

  • • 线程池类型fixed_auto_queue_size

  • • 大小:1

  • • 说明:为关键系统操作设计,确保读取操作能在高负载情况下得到优先处理。

配置方法

thread_pool.system_critical_read.type: fixed_auto_queue_size
thread_pool.system_critical_read.size: 1

system_critical_write线程池

  • • 用途:处理关键的系统级别写入操作。

  • • 线程池类型fixed_auto_queue_size

  • • 大小:1

  • • 说明:同样针对关键系统操作,确保写入操作的顺利进行。

配置方法

thread_pool.system_critical_write.type: fixed_auto_queue_size
thread_pool.system_critical_write.size: 1

watcher线程池

  • • 用途:处理Watchers任务,通常用于监控任务。

  • • 线程池类型scaling

  • • 保活时间:5分钟

  • • 最大线程池大小:1

  • • 说明:Elasticsearch的监控和报警框架Watcher依赖此线程池进行触发和处理。

配置方法

thread_pool.watcher.type: scaling
thread_pool.watcher.keep_alive: 5m
thread_pool.watcher.max: 1

3. 线程池类型和参数配置方法

Elasticsearch支持不同类型的线程池,适用于不同场景和工作负载。

3.1 固定大小线程池(fixed)

固定大小线程池用于处理请求,线程池大小固定,且有一个(可选的)有界队列用于处理无法立即执行的挂起请求。

  • • size:控制线程池中的线程数量。

  • • queue_size:控制挂起请求队列的大小,默认为-1表示无界。当请求到达且队列已满时,系统会中止请求。

thread_pool:
  write:
    size: 30
    queue_size: 1000

3.2 固定自动队列大小线程池(fixed_auto_queue_size)

该类型线程池类似于固定大小线程池,但挂起请求队列的大小会根据Little's Law的计算动态调整。随着处理的请求数量增加,队列大小可能会调整。

  • • size:线程池大小。

  • • queue_size:初始队列大小。

  • • min_queue_size:队列的最小大小。

  • • max_queue_size:队列的最大大小。

  • • auto_queue_frame_size:控制在调整队列之前需要完成的操作数量。

  • • target_response_time:目标响应时间,用于动态调整队列大小。

thread_pool:
  search:
    size: 30
    queue_size: 500
    min_queue_size: 10
    max_queue_size: 1000
    auto_queue_frame_size: 2000
    target_response_time: 1s

3.3 动态扩展线程池(scaling)

动态扩展线程池会根据工作负载动态调整线程数量。线程池的线程数量在core(核心线程数)和max(最大线程数)之间浮动。

  • • core:线程池的最小线程数。

  • • max:线程池的最大线程数。

  • • keep_alive:线程在无工作负载时保持活动的时间。

thread_pool:
  warmer:
    core: 1
    max: 8
    keep_alive: 2m

4. 分配处理器设置

线程池的大小通常是基于系统中分配的处理器数量决定的,合理配置处理器可以显著提升性能。

node.processors: 16

通过设置 node.processors 参数,用户可以限制分配给线程池的处理器数量。


5. 修改线程池配置

可以通过 elasticsearch.yml 文件或动态更新API来调整线程池的配置。例如,动态更新索引线程池的配置:

PUT /_cluster/settings
{
  "persistent": {
    "thread_pool.index.size": 40,
    "thread_pool.index.queue_size": 500
  }
}

6. 总结

Elasticsearch中的线程池机制极大地提高了系统的资源利用率和性能。通过合理配置各类线程池,用户能够根据自己的使用场景来优化集群的运行效率。在高并发环境下,优化线程池的配置尤其重要,能够有效地避免系统过载并减少请求失败的情况。

注:

本文档介绍版本为:7.14 ,其他版本可能会有所不同。

具体可以参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.14/modules-threadpool.html

更多精彩文章:

欢迎关注我的公众号“编程与架构”,原创技术文章第一时间推送。



编程与架构
专注于Java、大数据、AI以及开发运维技术的深入探索与分享。作为一名开源爱好者,致力于分享实战经验和前沿技术动态,帮助更多技术人提升技能。
 最新文章