Elasticsearch內存分配設置詳解

Elasticsearch內存分配設置詳解


   Elasticsearch默認安裝後設置的內存是1GB,對於任何一個現實業務來說,這個設置都太小了。如果你正在使用這個默認堆內存配置,你的集羣配置可能會很快發生問題。
 
這裏有兩種方式修改Elasticsearch的堆內存(下面就說內存好了),最簡單的一個方法就是指定ES_HEAP_SIZE環境變量。服務進程在啓動時候會讀取這個變量,並相應的設置堆的大小。設置命令如下:

export ES_HEAP_SIZE=10g

此外,你也可以通過命令行參數的形式,在程序啓動的時候把內存大小傳遞給它:

./bin/elasticsearch -Xmx10g -Xms10g

備註: 確保Xmx和Xms的大小是相同的,其目的是爲了能夠在java垃圾回收機制清理完堆區後不需要重新分隔計算堆區的大小而浪費資源,可以減輕伸縮堆大小帶來的壓力。
一般來說設置ES_HEAP_SIZE環境變量,比直接寫-Xmx10g  -Xms10g更好一點。


把內存的一半給Lucene


一個常見的問題是配置一個大內存,假設你有一個64G內存的機器,按照正常思維思考,你可能會認爲把64G內存都給Elasticsearch比較好,但現實是這樣嗎, 越大越好?
 
當然,內存對於Elasticsearch來說絕對是重要的,用於更多的內存數據提供更快的操作,而且還有一個內存消耗大戶-Lucene。
 
Lucene的設計目的是把底層OS裏的數據緩存到內存中。Lucene的段是分別存儲到單個文件中的,這些文件都是不會變化的,所以很利於緩存,同時操作系統也會把這些段文件緩存起來,以便更快的訪問。
 
Lucene的性能取決於和OS的交互,如果你把所有的內存都分配給Elasticsearch,不留一點給Lucene,那你的全文檢索性能會很差的。
 
最後標準的建議是把50%的內存給elasticsearch,剩下的50%也不會沒有用處的,Lucene會很快吞噬剩下的這部分內存用於文件緩存。


不要超過32G


這裏有另外一個原因不分配大內存給Elasticsearch,事實上jvm在內存小於32G的時候會採用一個內存對象指針壓縮技術。
 
在java中,所有的對象都分配在堆上,然後有一個指針引用它。指向這些對象的指針大小通常是CPU的字長的大小,不是32bit就是64bit,這取決於你的處理器,指針指向了你的值的精確位置。
 
對於32位系統,你的內存最大可使用4G。對於64系統可以使用更大的內存。但是64位的指針意味着更大的浪費,因爲你的指針本身大了。浪費內存不算,更糟糕的是,更大的指針在主內存和緩存器(例如LLC, L1等)之間移動數據的時候,會佔用更多的帶寬。
 
Java 使用一個叫內存指針壓縮的技術來解決這個問題。它的指針不再表示對象在內存中的精確位置,而是表示偏移量。這意味着32位的指針可以引用40億個對象,而不是40億個字節。最終,也就是說堆內存長到32G的物理內存,也可以用32bit的指針表示。
 
一旦你越過那個神奇的30-32G的邊界,指針就會切回普通對象的指針,每個對象的指針都變長了,就會使用更多的CPU內存帶寬,也就是說你實際上失去了更多的內存。事實上當內存到達40-50GB的時候,有效內存才相當於使用內存對象指針壓縮技術時候的32G內存。
 
這段描述的意思就是說:即便你有足夠的內存,也儘量不要超過32G,因爲它浪費了內存,降低了CPU的性能,還要讓GC應對大內存。


1TB內存的機器


32GB是ES一個內存設置限制,那如果你的機器有很大的內存怎麼辦呢?現在的機器內存普遍增長,你現在都可以看到有300-500GB內存的機器。

首先,我們建議編碼使用這樣的大型機
其次,如果你已經有了這樣的機器,你有兩個可選項:

  • 你主要做全文檢索嗎?考慮給Elasticsearch 32G內存,剩下的交給Lucene用作操作系統的文件系統緩存,所有的segment都緩存起來,會加快全文檢索。

  • 你需要更多的排序和聚合?你希望更大的堆內存。你可以考慮一臺機器上創建兩個或者更多ES節點,而不要部署一個使用32+GB內存的節點。仍然要堅持50%原則,假設你有個機器有128G內存,你可以創建兩個node,使用32G內存。也就是說64G內存給ES的堆內存,剩下的64G給Lucene。

如果你選擇第二種,你需要配置cluster.routing.allocation.same_shard.host:true。這會防止同一個shard的主副本存在同一個物理機上(因爲如果存在一個機器上,副本的高可用性就沒有了)。

 

swapping是性能的墳墓


這是顯而易見的,但是還是有必要說的更清楚一點,內存交換到磁盤對服務器性能來說是致命的。想想看一個內存的操作必須是快速的。
 
 
如果內存交換到磁盤上,一個100微秒的操作可能變成10毫秒,再想想那麼多10微秒的操作時延累加起來。不難看出swapping對於性能是多麼可怕。
 
最好的辦法就是在你的操作系統中完全禁用swapping。這樣可以暫時禁用:

swapoff -a

爲了永久禁用它,你可能需要修改/etc/fstab文件,這要參考你的操作系統相關文檔。

 
如果完全禁用swap,對你來說是不可行的。你可以降低swappiness 的值,這個值決定操作系統交換內存的頻率。這可以預防正常情況下發生交換。但仍允許os在緊急情況下發生交換。
 
對於大部分Linux操作系統,可以在sysctl中這樣配置:

vm.swappiness = 1

備註:swappiness設置爲1比設置爲0要好,因爲在一些內核版本,swappness=0會引發OOM(內存溢出)

簡單地說這個參數定義了系統對swap的使用傾向,默認值爲60,值越大表示越傾向於使用swap。可以設爲0,這樣做並不會禁止對swap的使用,只是最大限度地降低了使用swap的可能性。

通過sysctl -q vm.swappiness可以查看參數的當前設置。

修改參數的方法是修改/etc/sysctl.conf文件,加入vm.swappiness=xxx,並重起系統。這個操作相當於是修改虛擬系統中的/proc/sys/vm/swappiness文件,將值改爲XXX數值。

如果不想重起,可以通過sysctl -p動態加載/etc/sysctl.conf文件,但建議這樣做之前先清空swap。


 
最後,如果上面的方法都不能做到,你需要打開配置文件中的mlockall開關,它的作用就是運行JVM鎖住內存,禁止OS交換出去。在elasticsearch.yml配置如下:

bootstrap.mlockall: true


參考文章:http://www.cnblogs.com/jiu0821/p/5650027.html 

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