ElasticSearch CPU和内存占用高的优化记录

      公司最近使用ElasticSearch做为数据报表汇总引擎.上线三个月累计数据800万,可是今天忽然大面积出现查询超时,上服务器查看服务运行状况,发现cpu使用率高达300% mem 使用率也到了90%,下面记录了整个排查问题的过程html

     1.首先查看elastic cpu和mem占用状况java

//首先查看全部进程
# top
//找到对应的elasticserch运行的PID,查看占用内存比较高的线程,Ctrl+c 退出
#top -Hp 12345   
//为了下面方便调用API,将elasticsearch.yml
// xpack.security.enabled: false
//关闭认证,重启elasticsearch

    2.肯定是因为某个线程引发的情况,查询全部segment的驻留内存的状况node

//kibana 如下所有以kibanna为例
GET  _cat/segments?v&h=index,segment,size
//curl
#curl -XGET 'http://10.0.7.134:9200/ _cat/segments?v&h=index,segment,size'

    这里摘录一下,elasticsearch,segment,shard的区别程序员

Shard(分片) 
      一个Shard就是一个Lucene实例,是一个完整的搜索引擎。一个索引能够只包含一个Shard,只是通常状况下会用多个分片,能够拆分索引到不一样的节点上,分担索引压力。

segment 
     elasticsearch中的每一个分片包含多个segment,每个segment都是一个倒排索引;在查询的时,会把全部的segment查询结果汇总归并后最为最终的分片查询结果返回; 
     在建立索引的时候,elasticsearch会把文档信息写到内存bugffer中(为了安全,也一块儿写到translog),定时(可配置)把数据写到segment缓存小文件中,而后刷新查询,使刚写入的segment可查。 
虽然写入的segment可查询,可是尚未持久化到磁盘上。所以,仍是会存在丢失的可能性的。 
      因此,elasticsearch会执行flush操做,把segment持久化到磁盘上并清除translog的数据(由于这个时候,数据已经写到磁盘上,不在须要了)。 
当索引数据不断增加时,对应的segment也会不断的增多,查询性能可能就会降低。所以,Elasticsearch会触发segment合并的线程,把不少小的segment合并成更大的segment,而后删除小的segment。 
     segment是不可变的,当咱们更新一个文档时,会把老的数据打上已删除的标记,而后写一条新的文档。在执行flush操做的时候,才会把已删除的记录物理删除掉。

   3.没有发现特别占用内存和cpu的segment,接着查看node的内存和cpu的使用状况缓存

GET _cat/nodes?v

   参考: Day 19 ES内存那点事安全

 4.通过查找总体的cpu占用率仍是很高,接着查看,elastic运行日志发现服务器

//jvm gc
[gc][51125] overhead, spent [15s] collecting in the last [15.2s]

     这里摘录一下java jvm gc的解释curl

与C/C++相比,JAVA并不要求咱们去人为编写代码进行内存回收和垃圾清理。JAVA提供了垃圾回收器(garbage collector)来自动检测对象的做用域),可自动把再也不被使用的存储空间释放掉,也就是说,GC机制能够有效地防止内存泄露以及内存溢出。

JAVA 垃圾回收器的主要任务是:

分配内存
确保被引用对象的内存不被错误地回收
回收再也不被引用的对象的内存空间
凡事都有两面性。垃圾回收器在把程序员从释放内存的复杂工做中解放出来的同时,为了实现垃圾回收,garbage collector必须跟踪内存的使用状况,释放没用的对象,在完成内存的释放以后还须要处理堆中的碎片, 这样作一定会增长JVM的负担。

为何要了解JAVA的GC机制? 综上所述,除了做为一个程序员,精益求精是基本要求以外,深刻了解GC机制让咱们的代码更有效率,尤为是在构建大型程序时,GC直接影响着内存优化和运行速度。

     关于java程序的性能   G1 Garbage Collector *jvm

    [ElasticSearch填坑] 聚合请求致使GC故障  *elasticsearch

      生产环境elasticsearch的配置建议

      jvm如何优化java GC[译]

   5.查看节点状态

//kibana
_nodes/stats
//jvm 占用cpu 98% 内存 80%
须要提的一点就是 GC 是很是影响性能的,因此咱们来简单介绍一下 JVM 的机制。启动 JVM 虚拟机的时候,会分配固定大小的内存块,也就是堆 heap。堆又分红两组,Young 组是为新实例化的对象所分配的空间,比较小,通常来讲几百 MB,Young 组内又分为两个 survivor 空间。Young 空间满了后,就垃圾回收一次,还存活的对象放到幸存空间中,失效的就被移除。Old 组就是保存那些重启存活且一段时间不会变化的内容,对于 ES 来讲可能有 30 GB 内存是 Old 组,一样,满了以后就垃圾回收。

垃圾回收的时候,JVM 采用的是 STW(Stop The World) 机制,Young 组比较小还好,可是 Old 组可能须要几秒十几秒,那就是服务器无响应啊!因此咱们必须很是关注 GC 性能。

若是 ES 集群中常常有很耗时的 GC,说明内存不足,若是影响集群之间 ping 的话,就会退出集群,而后由于分片缘故致使更大的影响。咱们能够在节点状态中的 jvm 部分查看对应的数值,最重要是 heap_used_percent,若是大于 75,那么就要垃圾回收了,若是长期在 75 以上,那就是内存不足。

Elasticsearch技巧指南 **

  6.综合上述,能够定位

     6.1  jvm heap 设置比较小,默认是2g 本机有10g 配置内存为6g

     6.2 jvm GC 配置原来为 UseConcMarkSweepGC 更新为 UseG1GC

    修改elasticSeaerch安装目录下,jvm.options ,若是是集群则每一个节点都要改

//注释掉原来的配置
## GC configuration
#-XX:+UseConcMarkSweepGC
#-XX:CMSInitiatingOccupancyFraction=75
#-XX:+UseCMSInitiatingOccupancyOnly

//更新为
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50

//修改

-Xms6g
-Xms6g

    改elasticsearch.yml打开认证,从新启动ElasticSearch,在查看cpu没有那么高了,并且查询速度也快了

    貌似内存消耗仍是有点高,可是正常状况,经过使用

    _cat/segments?v查看是具体状况

相关文章
相关标签/搜索