首页 > 系统相关 >记:Elasticsearch 的 告警机制 和 jvm 内存分配

记:Elasticsearch 的 告警机制 和 jvm 内存分配

时间:2023-08-21 15:55:07浏览次数:46  
标签:删除 ## 索引 XX Elasticsearch 内存 jvm 文档

Elasticsearch 的告警机制导致的更新失败问题

总结:由于测试环境资源占用比例过高导致 elasticsearch 触发保护机制,导致的更新失败的问题

Es 告警日志:

查看服务器资源使用情况:

此时 Es 所在的挂载磁盘已经占用了 95%,Es 默认的保护机制:

属性名 属性值(可配置为固定值) 含义 保护措施
cluster.routing.allocation.disk.watermark.low 85% 低警戒水位线 不会将新的分片分配给磁盘使用率达到低警戒水位线的节点,不会影响新创建的索引的主分片,特别是之前从来没有分配过得分片。
cluster.routing.allocation.disk.watermark.high 90% 高警戒水位线 Elasticsearch 将尝试对磁盘使用率达到高警戒水位线的节点进行重新分片(将当前节点的数据转移到其他节点),此设置影响所有分片的分配,无论先前是否分配。
cluster.routing.allocation.disk.watermark.flood_stage 95% 洪泛警戒水位线 Elasticsearch 将对每个索引强制执行只读索引块(index.blocks.read_only_allow_delete)。这是防止节点耗尽磁盘空间的最后手段。待磁盘空间充裕后,会自动释放只读索引块。

从告警日志中看到,此时磁盘空间已经到了 90%,达到了高警戒水位线。此时 Elasticsearch 禁止了写操作,导致系统更新 Elasticsearch 资源失败。

如果想紧急恢复,提供以下措施,可以调高告警水位线:

PUT _cluster/settings
{
    "persistent":{
        "cluster.routing.allocation.disk.watermark.low":"90%",
        "cluster.routing.allocation.disk.watermark.high":"95%",
        "cluster.routing.allocation.disk.watermark.flood_stage":"97%"
    }
}

如想应急恢复索引功能,可以通过如下请求消除锁:

PUT */_settings?expand_wildcards=all
{
	"index.blocks.read_only_allow_delete": null
}

在此扩展一下索引块的五种不同的状态:

状态 作用
index.blocks.read_only 设置为 true 可以使索引和元数据只读。
index.blocks.read_only_allwo_delete 类似于 index.blocks.read_only ,但是允许删除索引释放磁盘资源。此时删除文档是不被允许的,仅可以删除索引。
index.blocks.read 设置为 true 代表禁止对该索引进行读操作。
index.blocks.write 设置为 true 代表禁止对该索引进行写操作,与read_only 不同,这个设置不影响元数据。
index.blocks.metadata 设置为 true 代表禁用元数据的读写。

需要注意,删除索引、删除文档存在的区别:

删除内容 过程
文档 在 Elasticsearch 中,删除和更新都是写操作,但是 Elasticsearch 中的文档是不可变的(immutable),因此不能被删除或者更改以展示其变更。
磁盘上的每个段都会有一个对应的 .del 文件。当删除请求发送后,文档并没有真正的被删除,而是在 .del 文件中被标记为删除。当该文档依然能够匹配查询,但是会在结果中被过滤掉。当段合并时,在 .del 文件中被比标记为删除的文档将不会被写入新段。
在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,在执行更新时,旧版本的文档在 .del 文档中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依旧能匹配查询,但是会在结果中被过滤掉。
索引 删除索引时很快的,基本上就是直接移除了和索引分片相关的文件。

可以看到删除文档时,并不是真正删除,只是逻辑删除。因此该文档所占用的空间并不会随着删除操作而马上释放,只有等下一次段合并的时候才会被真正的物理删除,这个时候才会释放磁盘空间。但是,在被查询到的文档标记删除的过程中同样需要占用磁盘空间,这个时候,删除操作并没有带来磁盘的资源释放,反而,磁盘使用率上升了,因此在删除过程中,需要保证集群磁盘有足够的余量,因为标记删除需要占用磁盘空间,如果磁盘空间不够,失败的概率还是很大的,严重时候,可能会造成集群崩溃和数据丢失。

所以 index.blocks.read_only_allwo_delete 禁用了删除文档操作,却可以删除索引。

回到最开始的问题,至此可以给出解决方案:

  1. 使用 api 暂时上调告警线,恢复正常的索引功能,避免小程序端业务功能瘫痪
  2. 整理服务器资源,清理日志文件和不需要用到的备份文件
  3. 回调告警水平线

以下为本次整理服务器资源过程中,使用了的 linux 命令:

命令 作用 说明
su es 切换用户 Es 不允许使用 root 用户启动
ps -eo pid,user,args 查看存活进程信息 -e 所有存活进程,-o 过滤参数
free -m 查看内存使用情况 -m 表示使用 M 作为单位来显示内存
df 文件夹 查看文件挂载内存分区位置
df -lh 查看系统服务器的磁盘空间 -l 本地文件,-h 以方便阅读的存储单位标识文件
du 统计文件夹磁盘消耗
rm -rf 删除文件,不可恢复 -r 递归 -f 静默删除

问题至此已经解决,以下记录本次问题带来的额外收货(问题定位错了,学到的额外知识)。


Elasticsearch 的 Jvm 内存分配为什么建议不大于 31 g(小于 32 g)?

首先我们可以查看一下 es 的启动参数:

[root@funfactory-share-01 ~]# ps -eo pid,user,args | grep "elasticsearch" | grep -v "grep"
29754 es       /data/app/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dio.netty.allocator.numDirectArenas=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Djava.locale.providers=SPI,JRE -Xms2g -Xmx2g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -Djava.io.tmpdir=/tmp/elasticsearch-7490738416214607905 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=32 -XX:GCLogFileSize=64m -Dlog4j2.formatMsgNoLookups=true -XX:MaxDirectMemorySize=1073741824 -Des.path.home=/data/app/elasticsearch -Des.path.conf=/data/app/elasticsearch/config -Des.distribution.flavor=default -Des.distribution.type=tar -Des.bundled_jdk=true -cp /data/app/elasticsearch/lib/* org.elasticsearch.bootstrap.Elasticsearch -d
29797 es       /data/app/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller

可以看到存在 jvm 启动参数 -Xms2g -Xmx2g ,我们都知道 es 是基于 java 开发的,不同的 es 版本实际上需要不同的 jdk 版本,这个在官网有版本对应。

项目上 test 环境使用的 es 是 7.10 版本的默认的对内存大小为 2g,早些年的版本为 1g。这个配置在 elasticsearch/config/jvm.options 文件中:

## JVM configuration

################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms2g
-Xmx2g

################################################################
## Expert settings
################################################################
##
## All settings below this section are considered
## expert settings. Don't tamper with them unless
## you understand what you are doing
##
################################################################

## GC configuration
8-13:-XX:+UseConcMarkSweepGC
8-13:-XX:CMSInitiatingOccupancyFraction=75
8-13:-XX:+UseCMSInitiatingOccupancyOnly

## G1GC Configuration
# NOTE: G1 GC is only supported on JDK version 10 or later
# to use G1GC, uncomment the next two lines and update the version on the
# following three lines to your version of the JDK
# 10-13:-XX:-UseConcMarkSweepGC
# 10-13:-XX:-UseCMSInitiatingOccupancyOnly
14-:-XX:+UseG1GC
14-:-XX:G1ReservePercent=25
14-:-XX:InitiatingHeapOccupancyPercent=30

## JVM temporary directory
-Djava.io.tmpdir=${ES_TMPDIR}

## heap dumps

# generate a heap dump when an allocation from the Java heap fails
# heap dumps are created in the working directory of the JVM
-XX:+HeapDumpOnOutOfMemoryError

# specify an alternative path for heap dumps; ensure the directory exists and
# has sufficient space
-XX:HeapDumpPath=data

# specify an alternative path for JVM fatal error logs
-XX:ErrorFile=logs/hs_err_pid%p.log

## JDK 8 GC logging
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:logs/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32
8:-XX:GCLogFileSize=64m

# JDK 9+ GC logging
9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
# BEGIN Log4j
-Dlog4j2.formatMsgNoLookups=true
# END Log4j

这里提供了两种方式修改 elasticsearch 的堆内存。最简单的方法是指定一个环境变量,在服务进程启动的时候指定这个变量的值,设置对应的堆大小,如:

export ES_HEAP_SIZE = 10g

也可以通过命令行参数的形式,在程序启动的时候把内存大小传递给它:

./bin/elasticsearch -Xmx10g -Xms10g

这里需要注意,确保堆内存最大值 Xmx 和最小值 Xms 的大小是相同的,防止程序在运行时改变堆内存的大小,这个是一个很耗资源的过程。

相信大家都听过一个说法:Elasticsearch 的 Jvm 内存分配为什么建议不大于 31 g。那么,为什么?

事实上,JVM 在内存小于 32 GB 的时候会使用一个内存对象指针压缩技术

在 java 中,所有的对象都分配在堆上,并通过一个指针进行引用。普通对象指针(oop)指向这些对象,通常大小为 CPU 的字长:32 位或 64 位,这取决于处理器,指针引用的就是这个 OOP 值的字节位置。

对于 32 位的系统,意味着堆内存大小最大为 4 GB。对应 64 位的系统,可以使用更大的内存,但是 64 位的指针,意味着很大的浪费,因为你的指针本身就已经更大了。更大的指针在主内存和各级缓存之间移动数据时,会占用更多的带宽。

Java 使用一个叫作 内存指针压缩(compressed oops)的技术来解决这个问题。 它的指针不再表示对象在内存中的精确位置,而是表示 偏移量 。这意味着 32 位的指针可以引用 40 亿个 对象 , 而不是 40 亿个字节。最终, 也就是说堆内存增长到 32 GB 的物理内存,也可以用 32 位的指针表示。

一旦你越过那个神奇的 ~32 GB 的边界,指针就会切回普通对象的指针。 每个对象的指针都变长了,就会使用更多的 CPU 内存带宽,也就是说你实际上失去了更多的内存。事实上,当内存到达 40–50 GB 的时候,有效内存才相当于使用内存对象指针压缩技术时候的 32 GB 内存。

即便你有足够的内存,也尽量不要 超过 32 GB。因为它浪费了内存,降低了 CPU 的性能,还要让 GC 应对大内存。

标签:删除,##,索引,XX,Elasticsearch,内存,jvm,文档
From: https://www.cnblogs.com/radish40/p/17646238.html

相关文章

  • 寄存器与内存在CPU计算中的作用
    cpu的计算是在内存上做的吗?计算过程中的数据存储在内存中,但CPU执行计算的过程是在寄存器中进行的,而不是直接在内存上进行。当需要使用内存中的数据时,CPU会将数据加载到寄存器中进行操作,并将结果存回内存。这样可以加快计算的速度,因为寄存器是位于CPU内部,速度比内存更快。然而,寄存......
  • 《深入浅出Java虚拟机 — JVM原理与实战》带你攻克技术盲区,夯实底层基础 —— 吃透cla
    前言介绍了解Java代码如何编译成字节码并在JVM上执行是非常重要的。这种理解可以帮助我们理解程序执行时发生的情况,确保语言特性符合逻辑,并在进行讨论时能够全面考虑各种因素和副作用。本文将深入探讨Java代码编译成字节码并在JVM上执行的过程。如果您对JVM的内部结构和字节码执行......
  • 深入了解Elasticsearch搜索引擎篇:倒排索引、架构设计与优化策略
    什么是倒排索引?有什么好处?倒排索引是一种用于快速检索的数据结构,常用于搜索引擎和数据库中。与传统的正排索引不同,倒排索引是根据关键词来建立索引,而不是根据文档ID。倒排索引的建立过程如下:首先,将每个文档拆分成一系列的关键词或词项,然后建立一个词项到文档的映射。对每个关键......
  • 我也来扒一扒python的内存回收机制!
    python的内存回收是面试中经常会问到一个问题,今天我来给大家深度剖析下python的内存回收和缓存机制 1、引用计数器我们知道,python是通过引用计数器来做内存回收的,下面我们来重点讲下引用计数器提到引用计数器,我们需要先讲下python中的环状双向链表refchain。1.1双向链表ref......
  • ORA-27102:内存不足
    错误信息【汉】ORA-27102:内存不足【英】ORA-27102:outofmemory环境CentOS7操作系统Oracle11G例使用dbca图形界面创建实例时报错。原因在创建时,Oracle检测到当前操作系统的内存不够,无法创建指定的SGA和PGA的实例。解决办法我们可以将解决分为两步,首先是排查内存的使用情况,再就......
  • java脚本模拟服务器内存溢出实战&服务器部署java项目
    一、背景:使用javaspringboot,实现linux服务器内存溢出情况。二、方案1、打包成war包,可以直接将war包部署在tomcat容器里2、springboot,打包成jar包。打的jar包,内置了tomcat,所以在服务器上,直接启jar包就行,没有必要放在tomcat容器里部署,在启动jar包时,可以配置线程池等。这......
  • 解密Nginx与Elasticsearch的协同高效:深入理解反向代理与全文搜索
    在当今高度互联的网络环境中,后端技术的结合与优化对于构建高性能应用至关重要。本篇博客将聚焦于两个关键主题:Nginx反向代理和Elasticsearch全文搜索,通过深入分析实现原理和代码示例,展示它们如何协同工作以提升系统性能。Nginx反向代理的作用Nginx不仅仅是一款高性能的Web服务器,还......
  • 构建高性能后端:探秘Nginx与Elasticsearch的技术协同
    在如今的信息时代,高性能的后端技术对于应用的成功至关重要。本文将深入探讨两个关键技术领域:Nginx反向代理和Elasticsearch全文搜索。通过详细的原理解析和实际代码示例,揭示它们如何协同工作,为应用的性能和效率提供强大支持。Nginx反向代理:背后的原理Nginx不仅是一款优秀的Web服务......
  • Nginx与Elasticsearch:高性能后端的黄金组合
    在追求高性能的后端开发中,Nginx与Elasticsearch是两个不可或缺的技术利器。本文将深入剖析这两者,探讨它们的协同作用,通过深入原理解析和实用代码示例,揭示它们如何共同构建高效的后端系统。构建高性能后端的首选:Nginx反向代理Nginx不仅是一款出色的Web服务器,还是一款强大的反向代理......
  • Nginx与Elasticsearch:高性能后端的完美融合
    在追求卓越后端性能的道路上,Nginx与Elasticsearch是一对黄金组合。本文将从深度原理解析和实际代码示例两个方面,探索这两项技术的协同作用,揭示它们如何共同构建高效的后端系统。打造高性能后端:Nginx反向代理Nginx不仅仅是一款优秀的Web服务器,更是一款强大的反向代理工具。通过将客......