ElasticSearch優(yōu)化系列二

ElasticSearch優(yōu)化系列二:機器設(shè)置(內(nèi)存)

預(yù)留一半內(nèi)存給Lucence使用

一個常見的問題是配置堆太大。你有一個64 GB的機器,覺得JVM內(nèi)存越大越好,想給Elasticsearch所有64 GB的內(nèi)存。

當(dāng)然,內(nèi)存對于Elasticsearch來說絕對是重要的,用于更多的內(nèi)存數(shù)據(jù)提供更快的操作。而且還有一個內(nèi)存消耗大戶-Lucene

Lucene的設(shè)計目的是把底層OS里的數(shù)據(jù)緩存到內(nèi)存中。Lucene的段是分別存儲到單個文件中的,這些文件都是不會變化的,所以很利于緩存,同時操作系統(tǒng)也會把這些段文件緩存起來,以便更快的訪問。

Lucene的性能取決于和OS的交互,如果你把所有的內(nèi)存都分配給Elasticsearch,不留一點給Lucene,那你的全文檢索性能會很差的。

最后標(biāo)準(zhǔn)的建議是把50%的內(nèi)存給elasticsearch,剩下的50%也不會沒有用處的,Lucene會很快吞噬剩下的這部分內(nèi)存。

32GB限制

給ES的內(nèi)存配置不是越大越好,建議不能超過32GB,不同jdk版本最大邊界值是不同的,對于32位小于32G JVM才采用內(nèi)存對象指針壓縮技術(shù),不然對象指針需要占用很大的內(nèi)存。

使用如下命令測試最大邊界值:

java -Xmx32767m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops? ?

bool UseCompressedOops? ? ? = false? ? ? ? {lp64_product}? ?

java -Xmx32766m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops? ?

bool UseCompressedOops? ? ? = true? ? ? ? ? {lp64_product}?

$ JAVA_HOME=`/usr/libexec/java_home -v 1.8` java -Xmx32766m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops? ?

bool UseCompressedOops? := true

$ JAVA_HOME=`/usr/libexec/java_home -v 1.8` java -Xmx32767m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops

bool UseCompressedOops? = false

在ES啟動日志中最好能夠看到壓縮對象指針為真。

heap size [15.8gb], compressed ordinary object pointers [true]

在java中,所有的對象都分配在堆上,然后有一個指針引用它。指向這些對象的指針大小通常是CPU的字長的大小,不是32bit就是64bit,這取決于你的處理器,指針指向了你的值的精確位置。

對于32位系統(tǒng),你的內(nèi)存最大可使用4G。對于64系統(tǒng)可以使用更大的內(nèi)存。但是64位的指針意味著更大的浪費,因為你的指針本身大了。浪費內(nèi)存不算,更糟糕的是,更大的指針在主內(nèi)存和緩存器(例如LLC, L1等)之間移動數(shù)據(jù)的時候,會占用更多的帶寬。

java 使用一個叫內(nèi)存指針壓縮的技術(shù)來解決這個問題。它的指針不再表示對象在內(nèi)存中的精確位置,而是表示偏移量。這意味著32位的指針可以引用40億個對象,而不是40億個字節(jié)。最終,也就是說堆內(nèi)存長到32G的物理內(nèi)存,也可以用32bit的指針表示。

一旦你越過那個神奇的30-32G的邊界,指針就會切回普通對象的指針,每個對象的指針都變長了,就會使用更多的CPU內(nèi)存帶寬,也就是說你實際上失去了更多的內(nèi)存。事實上當(dāng)內(nèi)存到達40-50GB的時候,有效內(nèi)存才相當(dāng)于使用內(nèi)存對象指針壓縮技術(shù)時候的32G內(nèi)存。

這段描述的意思就是說:即便你有足夠的內(nèi)存,也盡量不要超過32G,因為它浪費了內(nèi)存,降低了CPU的性能,還要讓GC應(yīng)對大內(nèi)存。

機器內(nèi)存大于64GB

你可以考慮一臺機器上創(chuàng)建兩個或者更多ES節(jié)點,而不要部署一個使用32+GB內(nèi)存的節(jié)點。仍然要 堅持50%原則,假設(shè) 你有個機器有128G內(nèi)存,你可以創(chuàng)建兩個node,使用32G內(nèi)存。也就是說64G內(nèi)存給ES的堆內(nèi)存,剩下的64G給Lucene。

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

swapping是性能的墳?zāi)?/p>

這是顯而易見的,但是還是有必要說的更清楚一點,內(nèi)存交換到磁盤對服務(wù)器性能來說是致命的。想想看一個內(nèi)存的操作必須是快速的。

如果內(nèi)存交換到磁盤上,一個100微秒的操作可能變成10毫秒,再想想那么多10微秒的操作時延累加起來。不難看出swapping對于性能是多么可怕。

最好的辦法就是在你的操作系統(tǒng)中完全禁用swapping。這樣可以暫時禁用:

sudo swapoff -a

為了永久禁用它,你可能需要修改/etc/fstab文件,這要參考你的操作系統(tǒng)相關(guān)文檔。

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

vm.swappiness = 1

備注:swappiness設(shè)置為1比設(shè)置為0要好,因為在一些內(nèi)核版本,swappness=0會引發(fā)OOM(內(nèi)存溢出)

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

bootstrap.mlockall: true

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容