暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

带你了解:Elasticsearch中Ingest的自动扩展

Elastic搜索 2025-01-06
143

 

正确确定Elasticsearch集群的大小并不是一件容易的事情。集群的最佳大小取决于其正在处理的工作负载,而这可能会随时间变化。自动扩展可以根据工作负载自动调整集群大小,无需人工干预。这不仅避免了为应对高峰使用而过度配置资源,还能防止因资源不足而导致的集群性能下降。

我们依赖这一机制,为我们的Elastic Cloud Serverless[1]服务用户免去为索引层[2]做大小决策的烦恼。Ingest自动扩展需要持续估算处理当前工作负载所需的资源,并及时配置和释放这些资源。

在这篇博客中,我们将探讨Elasticsearch中的Ingest自动扩展,内容包括:

  • • Elasticsearch中Ingest自动扩展的工作原理

  • • 我们用来量化集群索引工作负载的指标,以估算处理该工作负载所需的资源

  • • 这些指标如何驱动自动扩展决策

Ingest自动扩展概述

Elasticsearch中的Ingest自动扩展由一组由Elasticsearch自身公开的指标驱动。这些指标反映了索引层的Ingest负载和内存需求。Elasticsearch提供了一个自动扩展指标API,用于提供这些指标,使外部组件能够监控这些指标并决定是否需要调整集群大小(见图1)。

在Elastic Cloud Serverless服务中,有一个自动扩展器组件,它是一个Kubernetes控制器。自动扩展器定期轮询Elasticsearch自动扩展指标API,并根据这些指标计算所需的集群大小。如果所需的集群大小与当前大小不同,自动扩展器将调整集群大小,以便集群中的可用资源符合所需资源。这一调整不仅涉及集群中Elasticsearch节点的数量,还包括每个节点的CPU、内存和磁盘资源。

图1:Ingest自动扩展概述

需要注意的是,当集群遇到索引负载激增时,自动扩展过程可能需要一些时间来有效调整集群大小。尽管我们尽量缩短这一反应时间,但它不可能是瞬时的。因此,在集群扩展期间,Elasticsearch集群应能够暂时推迟处理接收到的负载,以防止因负载增加导致的集群不稳定问题。索引负载的增加可能会导致集群需要更多资源,即CPU、内存或磁盘。Elasticsearch具有保护机制,允许节点在任何资源成为瓶颈时推迟处理索引负载。

为了处理索引请求,Elasticsearch使用了基于节点可用核心数配置的专用线程池。如果索引负载增加导致CPU或其他资源成为瓶颈,新的索引请求将被排队。队列的最大大小[3]是有限的,任何在队列满时到达节点的请求都将被拒绝,并返回429 HTTP代码。

Elasticsearch还会跟踪处理当前索引请求所需的内存,如果索引缓冲区增长超过可用堆内存的10%[4],会拒绝新的索引请求(返回429)。这限制了索引使用的内存,确保节点不会内存不足。

Elastic Cloud Serverless服务依赖对象存储作为索引数据的主要存储。节点上的本地磁盘用于临时保存索引数据。Elasticsearch会定期将索引数据上传到对象存储,从而释放本地磁盘空间,因为我们依赖对象存储来保证索引文档的持久性。然而,在高索引负载下,节点可能在定期上传任务运行并释放本地磁盘空间之前耗尽磁盘空间。为了解决这种情况,Elasticsearch监控可用本地磁盘空间,并在必要时限制索引活动,同时尝试通过强制上传到对象存储来释放空间,而不是等待定期上传。这种限制会导致新的索引请求排队。

这些保护机制允许Elasticsearch集群暂时拒绝请求,并向客户端提供指示集群过载的响应,同时集群尝试扩展。这种推迟信号为客户端提供了减少负载或重试请求的机会,重试请求在集群扩展后应该能够成功。

指标

Elasticsearch中用于Ingest自动扩展的两个指标是Ingest负载和内存。

Ingest负载

Ingest负载表示需要多少线程来应对当前索引负载。自动扩展指标API公开了一系列Ingest负载值,每个索引节点对应一个。由于写线程池(处理索引请求)是根据节点上的CPU核心数配置的,这实际上确定了集群中处理索引工作负载所需的总核心数。

每个索引节点的Ingest负载由两个部分组成:

  • • 线程池利用率:在采样期间写线程池处理中索引请求的平均线程数。

  • • 排队的Ingest负载:处理排队的写请求所需的估计线程数。

每个索引节点的Ingest负载是这两个值的总和,涵盖了所有三个写线程池[5]。Elasticsearch集群的总Ingest负载是各个节点Ingest负载的总和。

node_ingestion_load = ∑(thread_pool_utilization + queued_ingestion_load)
total_ingestion_load = ∑(node_ingestion_load)

图2: Ingest负载组成部分

线程池利用率是线程池中繁忙线程数的指数加权移动平均值(EWMA)[6],每秒采样一次。配置了采样线程池利用率的EWMA,使过去10秒内的采样值对线程池利用率部分影响最大,而超过60秒的采样值影响非常小。

为了估算处理线程池中排队索引请求所需的资源,我们需要估算每个排队任务的执行时间。为此,每个线程池还提供请求执行时间的EWMA。索引请求的请求执行时间是从任务出队到工作线程开始执行所需的(时钟)时间。由于某些排队是可以接受的,并且应由线程池管理,我们尝试估算处理过多排队所需的资源。我们认为队列中的任务在30秒内是可管理的,并根据这一值为每150个排队项目估算一个额外线程。

queued_ingestion_load = queue_size × average_request_execution_time / 30s

注意,由于索引节点依赖定期将索引数据推送到对象存储,我们不需要根据索引数据总大小来扩展索引层。然而,索引工作负载的磁盘IO需求需要考虑在自动扩展决策中。Ingest负载同时表示索引节点的CPU需求和磁盘IO需求,因为写线程池工作线程同时处理CPU和IO工作,我们依赖时钟时间来估算处理排队请求所需的时间。

每个索引节点计算其Ingest负载,并定期将此值发布到主节点。主节点通过自动扩展指标API向自动扩展器提供每个节点的Ingest负载值。

内存

自动扩展指标API公开的内存指标包括节点内存和层内存。节点内存表示集群中每个索引节点的最小内存需求。层内存指标表示索引层中应可用的最小总内存。这些值仅表示最低要求,以确保每个节点能够处理基本索引工作负载并保存集群和索引元数据,同时确保层中包含足够的节点来容纳所有索引分片。

节点内存必须至少有500MB才能处理索引工作负载[7],以及每个索引的固定内存量[8]。这确保所有节点可以保存集群元数据,包括每个索引的元数据。层内存通过考虑索引字段映射的内存开销和分配到集群节点的每个打开分片所需的内存量来确定。目前,每个分片的内存需求使用固定估算值6MB。我们计划改进这个值。

每个索引的映射内存需求估算由托管该索引分片的数据节点之一计算。计算出的估算值发送到主节点。每当映射发生变化时,该估算值会更新并再次发布到主节点。主节点根据这些信息通过自动扩展指标API向自动扩展器提供节点和总内存指标。

集群扩展

自动扩展器负责通过公开的指标监控Elasticsearch集群,计算适应索引工作负载所需的理想集群大小,并相应地更新部署。这是通过根据Ingest负载和内存指标计算所需的总CPU和内存资源来完成的。所有节点的Ingest负载总和决定了索引层所需的总CPU核心数。

计算出的CPU需求和提供的最小节点和层内存资源映射到预定的一组集群大小。每个集群大小决定了节点数量以及每个节点的CPU、内存和磁盘大小。某个集群大小内的所有节点具有相同的硬件规格。CPU、内存和磁盘之间有一个固定比例,因此始终线性扩展这三种资源。现有的索引层集群大小基于节点大小,从4GB/2vCPU/100GB磁盘到64GB/32vCPU/1600GB磁盘不等。一旦Elasticsearch集群扩展到最大节点大小(64GB内存),任何进一步的扩展都将添加新的64GB节点,允许集群扩展到32个64GB节点。注意,这不是集群中Elasticsearch节点数量的硬上限,必要时可以增加。

每5秒,自动扩展器从主节点轮询指标,计算理想集群大小,如果与当前集群大小不同,它将相应地更新Elasticsearch Kubernetes部署。注意,实际的部署调整和添加或删除Elasticsearch节点以实现这一点由Kubernetes完成。为了避免集群大小的短期变化,我们在计算扩展下的理想集群大小时预留10%的余地,只有在过去15分钟内所有理想集群大小计算都表明需要缩减时,缩减才会生效。

目前,从指标增加到第一个Elasticsearch节点被添加到集群并准备处理索引负载的时间不到1分钟。

结论

在这篇博客中,我们解释了Elasticsearch中的Ingest自动扩展工作原理,涉及的不同组件以及用于量化处理索引工作负载所需资源的指标。我们相信,这样的自动扩展机制对于减少用户的Elasticsearch集群操作负担至关重要,因为它会在必要时自动增加集群中的可用资源。此外,通过在集群资源不再需要时缩小集群规模,这也有助于降低成本。

引用链接

[1]
 Elastic Cloud Serverless: https://www.elastic.co/docs/current/serverless
[2]
 索引层: https://www.elastic.co/search-labs/blog/stateless-your-new-state-of-find-with-elasticsearch
[3]
 队列的最大大小: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html
[4]
 增长超过可用堆内存的10%: https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-indexing-pressure.html
[5]
 所有三个写线程池: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html
[6]
 指数加权移动平均值(EWMA): https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
[7]
 才能处理索引工作负载: https://www.elastic.co/guide/en/elasticsearch/reference/current/size-your-shards.html#_consider_additional_heap_overheads
[8]
 每个索引的固定内存量: https://www.elastic.co/guide/en/elasticsearch/reference/current/size-your-shards.html#shard-count-recommendation

 

文章转载自Elastic搜索,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论