ElasticSearch CPU和內存占用高的優化記錄


      公司最近使用ElasticSearch作為數據報表匯總引擎.上線三個月累計數據800萬,但是今天突然大面積出現查詢超時,上服務器查看服務運行情況,發現cpu使用率高達300% mem 使用率也到了90%,下面記錄了整個排查問題的過程

     1.首先查看elastic cpu和mem占用情況

//首先查看所有進程
# top
//找到對應的elasticserch運行的PID,查看占用內存比較高的線程,Ctrl+c 退出
#top -Hp 12345   
//為了下面方便調用API,將elasticsearch.yml
// xpack.security.enabled: false
//關閉認證,重啟elasticsearch

    2.確定是由於某個線程引起的狀況,查詢所有segment的駐留內存的情況

//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的解釋

與C/C++相比,JAVA並不要求我們去人為編寫代碼進行內存回收和垃圾清理。JAVA提供了垃圾回收器(garbage collector)來自動檢測對象的作用域),可自動把不再被使用的存儲空間釋放掉,也就是說,GC機制可以有效地防止內存泄露以及內存溢出。

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

分配內存
確保被引用對象的內存不被錯誤地回收
回收不再被引用的對象的內存空間
凡事都有兩面性。垃圾回收器在把程序員從釋放內存的復雜工作中解放出來的同時,為了實現垃圾回收,garbage collector必須跟蹤內存的使用情況,釋放沒用的對象,在完成內存的釋放之后還需要處理堆中的碎片, 這樣做必定會增加JVM的負擔。

為什么要了解JAVA的GC機制? 綜上所述,除了作為一個程序員,精益求精是基本要求之外,深入了解GC機制讓我們的代碼更有效率,尤其是在構建大型程序時,GC直接影響着內存優化和運行速度。

     關於java程序的性能   G1 Garbage Collector *

    [ElasticSearch填坑] 聚合請求導致GC故障  *

      生產環境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查看是具體情況

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM