ElasticSearch CPU和內存佔用高的優化記錄出現GC

 

      公司最近使用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查看是具體情況

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章