目录
监控 API
调优
1、CPU使用率
ES中导致CPU 变高的因素
ES导致CPU 变高的解决方案
2、内存使用率
ES内存使用率 过高的可能因素
ES内存使用率 过高的处理方案
3、ES磁盘使用率
ES磁盘使用率过高的可能因素
4、ES 中GC频次
ES 中GC频次增加的可能因素
ES 中GC频次降低GC频次的方案
5、ES中fielddata内存
ES中fielddata内存使用量增加的可能因素
ES 中fielddata内存使用量增高时的解决方案
一个 Elasticsearch 集群至少包括一个节点和一个索引。或者它可能有一百个数据节点、三个单独的主节点,以及一小打客户端节点——这些共同操作一千个索引(以及上万个分片)。
不管集群扩展到多大规模,你都会想要一个快速获取集群状态的途径。Cluster Health
API 充当的就是这个角色。你可以把它想象成是在一万英尺的高度鸟瞰集群。它可以告诉你安心吧一切都好,或者警告你集群某个地方有问题。
让我们执行一下 cluster-health
API :
GET _cluster/health
response: 返回集群概览信息
{
"cluster_name": "elasticsearch_zach",
"status": "green",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 10,
"active_shards": 10,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
响应信息中最重要的一个指标 status
字段。状态可能是下列三个值之一:
green
所有的主分片和副本分片都已分配。你的集群是 100% 可用的。
yellow
所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。不过,你的高可用性在某种程度上被弱化。如果 更多的 分片消失,你就会丢数据了。把 yellow
想象成一个需要及时调查的警告。
red
至少一个主分片(以及它的全部副本)都在缺失中。这意味着你在缺少数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常。
剩下来的指标给你列出来集群的状态概要:
number_of_nodes
和 number_of_data_nodes
这个命名完全是自描述的。active_primary_shards
指出你集群中的主分片数量。这是涵盖了所有索引的汇总值。active_shards
是涵盖了所有索引的_所有_分片的汇总值,即包括副本分片。relocating_shards
显示当前正在从一个节点迁往其他节点的分片的数量。通常来说应该是 0,不过在 Elasticsearch 发现集群不太均衡时,该值会上涨。比如说:添加了一个新节点,或者下线了一个节点。initializing_shards
是刚刚创建的分片的个数。比如,当你刚创建第一个索引,分片都会短暂的处于 initializing
状态。这通常会是一个临时事件,分片不应该长期停留在 initializing
状态。你还可能在节点刚重启的时候看到 initializing
分片:当分片从磁盘上加载后,它们会从 initializing
状态开始。unassigned_shards
是已经在集群状态中存在的分片,但是实际在集群里又找不着。通常未分配分片的来源是未分配的副本。比如,一个有 5 分片和 1 副本的索引,在单节点集群上,就会有 5 个未分配副本分片。如果你的集群是 red
状态,也会长期保有未分配分片(因为缺少主分片)。如果发现status 变为red ,我们就需要进一步排查具体原因;定位具体那个分片的索引有问题;执行以下API
GET _cluster/health?level=indices
response 有关每个索引的细节(状态、分片数、未分配分片数等等);
{
"cluster_name": "elasticsearch_zach",
"status": "red",
"timed_out": false,
"number_of_nodes": 8,
"number_of_data_nodes": 8,
"active_primary_shards": 90,
"active_shards": 180,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 20
"indices": {
"v_1": {
"status": "green",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
},
"v_2": {
"status": "red",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 20
},
"v_3": {
"status": "green",
"number_of_shards": 10,
"number_of_replicas": 1,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
},
....
}
}
可以看到 v_2
索引就是让集群变 red
的那个索引;
我们还可以看到这个索引曾经有 10 个主分片和一个副本,而现在这 20 个分片全不见了。可以推测,这 20 个索引就是位于从我们集群里不见了的那两个节点上。
GET _cluster/health?level=shards
shards
选项会提供一个详细得多的输出,列出每个索引里每个分片的状态和位置。这个输出有时候很有用,但是由于太过详细会比较难用。
以上是ES 的原生API,也可以搭建kbana 等客户端界面更好的观察集群状态;
调优是一个优化程序运行性能的过程,需要结合经验,分析系统数据来找到性能瓶颈;然后有针对性的去优化提高性能;那么对于es 这种java 语言编程的程序,我们可以从以下几个方面去分析:
CPU使用率是指在一段时间内CPU执行程序的百分比,它是衡量系统资源利用率的一种指标。
详细说明:
在Elasticsearch中,高的CPU使用率通常意味着节点正在执行大量的计算任务,这可能是因为索引和搜索操作的负载较大,也可能是因为节点正在进行数据复制和分片重新平衡等任务。因此,高的CPU使用率通常是Elasticsearch性能瓶颈的一个指标。
查询负载增加:当 Elasticsearch 集群承受的查询负载增加时,会导致 CPU 使用率变高。这通常发生在索引大量新数据或者搜索流量增加的情况下。
索引负载增加:当 Elasticsearch 集群承受的索引负载增加时,会导致 CPU 使用率变高。这通常发生在索引大量新数据的情况下。
GC:当 Elasticsearch 的 Java 进程发生垃圾回收(GC)时,会导致 CPU 使用率变高。GC 是清理 Java 堆内存中不再使用的对象,它是 Java 程序中自带的机制,当 Java 堆内存中的对象数量增加时,GC 的频率和时间也会相应增加。
机器性能不足:当 Elasticsearch 部署的机器性能不足时,会导致 CPU 使用率变高。例如,CPU 处理器的速度较慢,内存不足,磁盘 I/O 较慢等。
插件/脚本等造成的性能问题:当 Elasticsearch 使用的插件或脚本存在性能问题时,会导致 CPU 使用率变高。在某些情况下,某些插件和脚本可能会影响 Elasticsearch 的性能,例如使用复杂的脚本或者调用较慢的第三方库。
总之,当 Elasticsearch 集群处理数据量增加、索引负载增加、查询负载增加、GC 或者机器性能不足等情况时,会导致 CPU 使用率变高。为了避免这种情况的发生,可以采取一些优化策略,如添加更多的节点、升级硬件等。
调整集群配置。可以通过调整Elasticsearch集群的配置来减少CPU的使用率。例如,可以调整查询的并发数、增加分片的数量、减少索引的副本数等,来减轻CPU的负担。
优化查询语句。复杂的查询语句可能会导致CPU的使用率飙升。因此,可以考虑优化查询语句,使用更简单、更高效的查询语句来减少CPU的使用率。
关闭不必要的插件。Elasticsearch的插件可以扩展其功能,但某些插件可能会占用大量的CPU资源。因此,可以考虑关闭某些不必要的插件来减少CPU的使用率。
增加硬件资源。如果Elasticsearch集群的CPU使用率经常超过限制,可能需要考虑增加硬件资源,例如增加CPU核心数量或升级CPU型号,以提高集群的性能。
增加集群规模。如果Elasticsearch集群的CPU使用率经常超过限制,还可以考虑增加集群规模,将负载分摊到多台机器上,以提高集群的性能。
调整集群中节点的负载均衡策略。Elasticsearch的负载均衡策略可能会导致某些节点的CPU使用率过高。因此,可以考虑调整负载均衡策略,将负载更均衡地分配到各个节点上。
Elasticsearch集群的CPU使用率升高时,可以考虑调整哪些参数:
indices.store.throttle.max_bytes_per_sec: 索引写入速度控制参数,用于限制每秒写入的数据量。如果写入速度太快,可能会导致CPU使用率过高。可以降低该参数的值来减缓写入速度。该参数的最优值取决于硬件配置和写入负载,一般建议将其设置为每秒写入速率的80%到90%。例如,如果每秒写入速率为50MB/s,则该参数的最优值可能在40MB/s到45MB/s之间。
indices.memory.index_buffer_size: 索引缓冲区大小。如果该值太小,会导致频繁的IO操作,从而增加CPU负载。可以适当增大该值来减少IO操作。该参数的最优值取决于可用内存、索引大小和查询负载等因素,一般建议将其设置为可用内存的20%到30%。例如,如果集群有100GB的可用内存,该参数的最优值可能在20GB到30GB之间。
indices.fielddata.cache.size: 字段数据缓存大小。如果字段数据缓存过小,可能会导致频繁的磁盘读取,从而增加CPU负载。可以适当增大该值来减少磁盘读取操作。该参数的最优值取决于字段数据大小和查询负载等因素,一般建议将其设置为可用内存的20%到30%。例如,如果集群有100GB的可用内存,该参数的最优值可能在20GB到30GB之间。
indices.queries.cache.size: 查询缓存大小。如果查询缓存过小,可能会导致频繁的查询操作,从而增加CPU负载。可以适当增大该值来减少查询操作。该参数的最优值取决于查询负载,一般建议将其设置为查询缓存占用可用内存的20%到30%。例如,如果集群有100GB的可用内存,该参数的最优值可能在20GB到30GB之间。
indices.recovery.max_bytes_per_sec: 索引恢复速度控制参数,用于限制每秒恢复的数据量。如果恢复速度太快,可能会导致CPU使用率过高。可以降低该参数的值来减缓恢复速度。该参数的最优值取决于恢复速度和集群负载,一般建议将其设置为每秒恢复速率的80%到90%。例如,如果每秒恢复速率为50MB/s,则该参数的最优值可能在40MB/s到45MB/s之间。
indices.search.slowlog.threshold.query.warn: 查询慢日志告警阈值。如果查询操作太慢,可能会导致CPU使用率过高。可以降低该参数的值来快速发现查询慢的问题。该参数的最优值取决于查询负载和业务需求,一般建议将其设置为查询执行时间的90%到95%。例如,如果查询执行时间的中位数为1秒,则该参数的最优值可能在900ms到950ms之间。
当前使用的内存量占可用内存总量的比例。
详细说明:
Elasticsearch 会使用 JVM 来运行,因此 JVM 的内存分配对 Elasticsearch 的性能非常重要。默认情况下,Elasticsearch 的 JVM 内存分配为 1GB,但在生产环境中通常需要将其调整为更大的值。
Elasticsearch 将内存分为两部分:堆内存和非堆内存。堆内存用于存储文档、字段和查询缓存等数据,非堆内存用于存储索引缓存、文件系统缓存和其他内部缓存等数据。
Elasticsearch 会自动管理缓存,以确保常用的数据在内存中。当内存不足时,Elasticsearch 会将较少使用的数据从内存中移除,并将其存储到磁盘上。
对于单个节点的 Elasticsearch 集群,通常建议将 JVM 堆内存设置为总内存的一半,以留出一定的空间给操作系统和其他进程使用。而对于大型集群,建议将 JVM 堆内存设置为 30GB 到 32GB。
在 Java 中,所有的对象都分配在堆上,并通过一个指针进行引用。 普通对象指针(OOP)指向这些对象,通常为 CPU 字长 的大小:32 位或 64 位,取决于你的处理器。指针引用的就是这个 OOP 值的字节位置。
对于 32 位的系统,意味着堆内存大小最大为 4 GB。对于 64 位的系统, 可以使用更大的内存,但是 64 位的指针意味着更大的浪费,因为你的指针本身大了。更糟糕的是, 更大的指针在主内存和各级缓存(例如 LLC,L1 等)之间移动数据的时候,会占用更多的带宽。
Java 使用一个叫作 内存指针压缩(compressed oops)的技术来解决这个问题。 它的指针不再表示对象在内存中的精确位置,而是表示 偏移量 。这意味着 32 位的指针可以引用 40 亿个 对象 , 而不是 40 亿个字节。最终, 也就是说堆内存增长到 32 GB 的物理内存,也可以用 32 位的指针表示。
一旦你越过那个神奇的 ~32 GB 的边界,指针就会切回普通对象的指针。 每个对象的指针都变长了,就会使用更多的 CPU 内存带宽,也就是说你实际上失去了更多的内存。事实上,当内存到达 40–50 GB 的时候,有效内存才相当于使用内存对象指针压缩技术时候的 32 GB 内存。
这段描述的意思就是说:即便你有足够的内存,也尽量不要 超过 32 GB。因为它浪费了内存,降低了 CPU 的性能,还要让 GC 应对大内存。
索引的大小和数量:索引的大小和数量会直接影响 Elasticsearch 使用的内存量。较大的索引需要更多的内存来处理,而较小的索引则需要较少的内存。
查询负载:查询负载是指 Elasticsearch 在任何给定时刻处理的查询数量和类型。更多的查询负载需要更多的内存来处理和缓存查询结果。
JVM 堆内存大小:Elasticsearch 在 JVM 堆内存中缓存文档、字段和查询结果等数据,堆内存的大小直接影响 Elasticsearch 的性能。通常,增加堆内存大小可以提高 Elasticsearch 的性能,但是在可用内存受限的情况下,过大的堆内存大小可能会导致系统负载过重,甚至导致 OutOfMemoryError 错误。
硬件资源:Elasticsearch 的内存使用率还受限于硬件资源,包括 CPU、磁盘和网络带宽等。如果硬件资源不足,可能会导致 Elasticsearch 性能下降,甚至无法正常运行。
Elasticsearch 版本:Elasticsearch 版本之间的内存使用率也可能有所不同。较新的版本通常会更有效地利用内存,提高性能和稳定性。
综上所述,Elasticsearch 的内存使用率受多种因素影响,需要根据具体情况进行分析和调整,以优化性能和稳定性。
检查Elasticsearch集群中是否有索引或搜索查询的负载异常,这可能导致内存使用率飙升。可以使用Elasticsearch的监控工具或REST API来查看负载和性能指标,并识别问题所在。
调整JVM的堆内存大小。JVM是Elasticsearch节点的内存管理器,可以通过调整JVM的堆内存大小来控制Elasticsearch的内存使用率。可以通过在elasticsearch.yml文件中设置-Xms和-Xmx参数来增加或减少JVM的堆内存大小。注意,不要将JVM的堆内存大小设置过小,否则会影Elasticsearch的性能。
减小索引分片的数量。索引分片是Elasticsearch的分布式存储机制,但太多的分片会占用过多的内存资源。可以通过减小索引分片的数量来降低内存使用率。
使用更高效的查询。复杂的查询可能需要占用更多的内存资源,因此,可以尝试使用更高效的查询来降低内存使用率。例如,使用过滤器而不是查询语句来获取数据,或使用聚合操作来减少数据的返回。
增加硬件资源。如果Elasticsearch集群的内存使用率经常超过限制,可能需要考虑增加硬件资源,例如增加内存或CPU,以满足集群的性能需求。
ES内存使用率过高,可以考虑调整哪些参数:
indices.memory.index_buffer_size:该参数控制索引模块使用的内存缓冲区大小。如果内存使用率升高,可以尝试降低该参数的值,以减少索引模块占用的内存。不过,降低该参数的值可能会降低索引性能。此参数应该根据索引的大小和使用情况进行调整。建议将其设置为每个索引的可用堆内存的5%-10%。
indices.fielddata.cache.size:该参数控制字段数据缓存的大小。如果内存使用率升高,可以尝试降低该参数的值,以减少字段数据缓存占用的内存。不过,降低该参数的值可能会降低查询性能。此参数应该设置为尽可能大的值,以利用可用的内存来缓存字段数据。建议设置为10%-30%的可用堆内存。
indices.queries.cache.size:该参数控制查询缓存的大小。如果内存使用率升高,可以尝试降低该参数的值,以减少查询缓存占用的内存。不过,降低该参数的值可能会降低查询性能。此参数应该设置为尽可能大的值,以利用可用的内存来缓存查询。建议设置为10%-30%的可用堆内存。
indices.breaker.*:该参数控制Elasticsearch使用的熔断器(circuit breaker)阈值。熔断器是一种保护机制,用于防止过度使用内存和磁盘等资源。如果内存使用率升高,可以尝试调整熔断器阈值,以避免过度使用内存。
indices.recovery.max_bytes_per_sec:该参数控制恢复速度。如果内存使用率升高,可以尝试降低该参数的值,以降低恢复操作占用的内存。 此参数应该根据网络带宽进行调整,以确保恢复操作不会占用过多的内存。建议将其设置为网络带宽的70%-80%。
磁盘使用率是指已用磁盘空间和可用磁盘空间之间的比率,通常以百分比形式表示
详细说明:
关于磁盘使用率可详细描述的部分较少,这里说明一下常见的几种磁盘类型:
机械硬盘(HDD):机械硬盘是一种传统的存储设备,使用旋转的磁盘和移动的磁头来读写数据。它们相对较便宜,但速度较慢,因此不适合对性能要求较高的应用。
固态硬盘(SSD):固态硬盘使用闪存来存储数据,速度比机械硬盘更快,因此可以提供更好的性能。它们相对较昂贵,但在需要高性能的应用场景中通常更受欢迎。
NVMe硬盘:NVMe硬盘是一种专为固态硬盘设计的高速接口,比SATA接口的固态硬盘更快,因此提供更高的性能。
分布式文件系统:Elasticsearch还支持使用分布式文件系统作为存储后端,如Hadoop Distributed File System(HDFS)和Amazon S3。这些系统通常用于大规模数据存储和分析,但也可以用于Elasticsearch。
数据量:Elasticsearch的磁盘使用率与数据量直接相关,因为数据存储在磁盘上。如果数据量增加,磁盘使用率也会相应增加。
索引设置:Elasticsearch支持多种索引设置,如分片和副本,这些设置会影响数据在磁盘上的存储方式和占用空间的大小。例如,分片数量越多,每个分片占用的磁盘空间就越小,但需要更多的分片可能会导致额外的磁盘空间占用。
索引更新频率:当索引频繁更新时,会导致Elasticsearch写入更多的数据到磁盘上,从而增加磁盘使用率。
删除操作:在Elasticsearch中,删除文档不会立即释放磁盘空间,而是通过后台的段合并(segment merge)操作来回收空间。如果经常删除文档,可能需要定期执行段合并操作,否则会导致磁盘使用率持续增加。
数据复制:Elasticsearch支持副本机制,即将数据复制到其他节点以实现高可用性。这意味着每个副本都需要占用额外的磁盘空间。
磁盘类型:不同类型的磁盘对性能和空间占用有不同的影响。例如,固态硬盘通常比机械硬盘更快,但通常也更昂贵,而机械硬盘则更适合低成本应用。
ES磁盘使用率磁盘使用率升高时处理方案:
添加更多的节点:可以通过添加更多的节点来扩展集群的存储能力,从而减轻单个节点的负担。
删除旧的或不需要的数据:可以通过删除旧的或不需要的数据来释放磁盘空间。但是,在删除数据之前,请确保您不再需要这些数据,因为数据删除是不可逆的操作。
压缩索引:Elasticsearch提供了一些工具来压缩索引,可以在不降低性能的情况下减小索引的大小。
增加磁盘空间:如果磁盘使用率升高是由于磁盘空间不足导致的,可以考虑增加磁盘空间。
调整文档的存储方式:可以通过调整文档的存储方式来减小磁盘使用率。例如,可以将文档中的某些字段设置为不索引,或者将某些字段设置为压缩存储。
指垃圾回收器在一定时间内执行的次数,它是一个反映JVM垃圾回收效率的指标。
详细说明:
这里指的是老年代的GC频次,老年代用来存储较老的对象空间,这些对象预期是长久的并且持续了很长时间。在Elasticsearch节点中最大可以设置为30GB。
一个缓慢的GC可能有1s甚至15s以上,从集群稳定性的角度来说是不可接受的。一个频繁长时间GC的集群是重负载并且没有足够内存的。这些长时间GC将使节点短暂离开集群,在Elasticsearch中为了保持集群的稳定和可用的副本,这种不稳定因素经常导致重新迁移分片。当集群尝试服务正常的索引(写入)和查询时,会增加网络流量和磁盘I/O。
在Elasticsearch集群的垃圾回收器替换成G1后,GC的频次和持续时间均有明显改善。
JVM堆内存不足:当JVM堆内存不足时,会导致GC频繁触发,以释放内存空间。这种情况通常是由于索引数据量增加或者查询负载增加等原因导致的。
索引数据过多:当索引数据量过多时,会占用大量的内存空间,导致JVM堆内存不足,从而引发GC频繁触发。
查询压力过大:当查询压力过大时,会导致Elasticsearch集群需要处理大量的查询请求,从而导致JVM堆内存不足,引发GC频繁触发。
代码逻辑问题:有时候可能存在代码逻辑问题,例如内存泄漏等,也会导致JVM堆内存占用过高,从而引发GC频繁触发。
增加JVM堆内存大小:GC频次过高的一个主要原因是JVM内存不足,因此增加JVM堆内存大小可以有效降低GC频次。一般来说,JVM堆内存大小应该设置为应用程序所需要的最小值加上一定的余量,以确保系统具有足够的内存。
优化查询和索引操作:查询和索引操作是Elasticsearch集群中最耗费内存和CPU资源的操作,因此可以通过优化查询和索引操作来降低GC频次。例如,可以使用filter代替query,避免使用过多的聚合操作,避免使用过多的脚本等。
使用合适的垃圾回收器:不同的垃圾回收器有不同的GC算法和优化策略,选择合适的垃圾回收器可以降低GC频次。一般来说,CMS垃圾回收器比较适合应用程序的实时处理,而G1垃圾回收器则适合大型堆内存的应用程序。
使用合适的JVM参数:合适的JVM参数可以对Elasticsearch集群的GC频次产生重要影响。例如,可以通过设置合适的堆内存大小、调整垃圾回收器的参数等方式来降低GC频次。
fielddata内存使用量是指已经被加载到内存中的fielddata的大小。
详细说明:
当在Elasticsearch中对一个字段使用聚合、排序、脚本或者用于全文搜索时,该字段的fielddata就会被加载到内存中进行操作。fielddata是一种用于对文本类型的字段进行排序和聚合的数据结构。
如果一个集群中有大量的字段需要在内存中加载fielddata,那么这个指标可能会对集群性能产生负面影响。因此,需要根据实际情况来调整fielddata的使用策略,以平衡内存的使用和查询性能的需求。
内存不足:当fielddata内存使用量过高时,可能会导致内存不足,从而影响Elasticsearch集群的运行。这可能会导致请求被拒绝、节点故障等问题。
垃圾回收:当fielddata内存使用量过高时,垃圾回收器会频繁执行,这可能会导致性能下降。特别是在大型集群中,这可能会导致所有节点的性能下降,进而影响整个集群。
磁盘使用量:当fielddata内存使用量过高时,Elasticsearch可能会将部分数据写入磁盘,从而占用更多的磁盘空间。如果磁盘空间不足,可能会影响Elasticsearch集群的稳定性。
使用 doc values 替代 fielddata:doc values 是一种结构化的、只读的数据结构,可以直接被用于排序、聚合和脚本,与 fielddata 相比可以减少内存使用。可以使用 doc_values 属性将字段显式地配置为使用 doc values。
避免过度使用 text 类型的字段:text 类型的字段会产生 fielddata,如果不需要进行全文搜索、聚合、排序等操作,可以考虑使用 keyword 类型的字段来替代。
减少不必要的聚合操作:聚合操作会对 fielddata 进行操作,如果聚合操作不是必须的,可以考虑避免使用。
增加 fielddata 缓存大小:可以通过在配置文件中设置 indices.fielddata.cache.size 来增加 fielddata 缓存大小,从而减少 fielddata 的内存使用。
减少索引的字段数:减少索引的字段数可以减少 fielddata 的内存使用。
注意,以上优化思路需要根据具体情况来判断选择,而ES 官方手册中建议我们不要轻易去调整这些配置参数,因为这些参数都是基于多年实际使用中配置好的,换句话说,当前集群的性能已经可以满足绝大多数的使用场景;如果你修改了某些参数,可能会引发一些未知问题,从而导致集群处于一个不佳性能的状态;而多数优化的前提就是回复集群原来默认配置就可以解决一些性能问题;