提升性能: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中的线程池在处理并发操作、优化资源使用和提高性能方面起着至关重要的作用。下面将详细介绍 generic
、index
、search
、get
、bulk
、snapshot
、warmer
、refresh
和 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
更多精彩文章:
欢迎关注我的公众号“编程与架构”,原创技术文章第一时间推送。