elasticsearch出現OutOfMemoryError故障分析及處理

最近我們的elasticsearch6.6.1集羣出現了停止服務的故障,客戶端提示多個節點連接無響應。檢查服務器上的日誌,發現如下錯誤日誌:

在這裏插入圖片描述

從錯誤日誌可以看到,jvm首先進行了Full GC。一般老年代空間只有在新生代對象轉入及創建爲大對象、大數組時纔會出現不足的現象。所謂大對象,是指需要大量連續內存空間的java對象,例如很長的數組,此種對象會直接進入老年代,而老年代雖然有很大的剩餘空間,但是無法找到足夠大的連續空間來分配給當前對象,此種情況就會觸發JVM進行Full GC。

如果執行Full GC後空間仍然不足,則會拋出如下錯誤:

java.lang.OutOfMemoryError: Java heap space

思路

當然,我們首先想到的肯定是調整該節點的jvm啓動參數,比如提高jvm.options的xmx等參數,然後重啓集羣恢復服務。

但是這只是治標不治本的方法,我在參考[2]中找到了elasticsearch出現這個問題的原因和解決辦法:

因爲默認情況下es對字段數據緩存(Field Data Cache)大小是無限制的,查詢時會把字段值放到內存,特別是facet查詢,對內存要求非常高,它會把結果都放在內存,然後進行排序等操作,一直使用內存,直到內存用完,當內存不夠用時就有可能出現out of memory錯誤。

解決方法

  1. 設置es的緩存類型爲Soft Reference,它的主要特點是據有較強的引用功能。只有當內存不夠的時候,才進行回收這類內存,因此在內存足夠的時候,它們通常不被回收。另外,這些引 用對象還能保證在Java拋出OutOfMemory 異常之前,被設置爲null。它可以用於實現一些常用圖片的緩存,實現Cache的功能,保證最大限度的使用內存而不引起OutOfMemory。在es的配置文件加上index.cache.field.type: soft即可。

  2. 設置es最大緩存數據條數和緩存失效時間,通過設置index.cache.field.max_size: 50000來把緩存field的最大值設置爲50000,設置index.cache.field.expire: 10m把過期時間設置成10分鐘。

另外補充一下,通過優化jvm參數也可以改善出現Full GC的概率,由於elasticsearch計算節點經常要在堆中分配大對象,爲了解決分配大對象引來Full GC的問題,CMS垃圾收集器提供了一個可配置的參數,即-XX:+UseCMSCompactAtFullCollection開關參數,用於在“享受”完Full GC服務之後額外免費贈送一個碎片整理的過程,內存整理的過程無法併發的,空間碎片問題沒有了,但提頓時間不得不變長了,JVM設計者們還提供了另外一個參數 -XX:CMSFullGCsBeforeCompaction,這個參數用於設置在執行多少次不壓縮的Full GC後,跟着來一次帶壓縮的。

參考

  1. JVM頻繁Full GC的情況及應對策略
  2. Elasticsearch生產環境遇到的問題以及解決方案
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章