ElasticSearch優(yōu)化系列二:機(jī)器設(shè)置(內(nèi)存)
預(yù)留一半內(nèi)存給Lucence使用
一個常見的問題是配置堆太大唉堪。你有一個64 GB的機(jī)器模聋,覺得JVM內(nèi)存越大越好,想給Elasticsearch所有64 GB的內(nèi)存唠亚。
當(dāng)然链方,內(nèi)存對于Elasticsearch來說絕對是重要的,用于更多的內(nèi)存數(shù)據(jù)提供更快的操作灶搜。而且還有一個內(nèi)存消耗大戶-Lucene
Lucene的設(shè)計(jì)目的是把底層OS里的數(shù)據(jù)緩存到內(nèi)存中祟蚀。Lucene的段是分別存儲到單個文件中的,這些文件都是不會變化的割卖,所以很利于緩存前酿,同時操作系統(tǒng)也會把這些段文件緩存起來,以便更快的訪問鹏溯。
Lucene的性能取決于和OS的交互罢维,如果你把所有的內(nèi)存都分配給Elasticsearch,不留一點(diǎn)給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位的指針意味著更大的浪費(fèi)化焕,因?yàn)槟愕闹羔槺旧泶罅恕@速M(fèi)內(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)存帶寬,也就是說你實(shí)際上失去了更多的內(nèi)存撕攒。事實(shí)上當(dāng)內(nèi)存到達(dá)40-50GB的時候陡鹃,有效內(nèi)存才相當(dāng)于使用內(nèi)存對象指針壓縮技術(shù)時候的32G內(nèi)存。
這段描述的意思就是說:即便你有足夠的內(nèi)存抖坪,也盡量不要超過32G萍鲸,因?yàn)樗速M(fèi)了內(nèi)存,降低了CPU的性能擦俐,還要讓GC應(yīng)對大內(nèi)存脊阴。
機(jī)器內(nèi)存大于64GB
你可以考慮一臺機(jī)器上創(chuàng)建兩個或者更多ES節(jié)點(diǎn),而不要部署一個使用32+GB內(nèi)存的節(jié)點(diǎn)蚯瞧。仍然要 堅(jiān)持50%原則嘿期,假設(shè) 你有個機(jī)器有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的主副本存在同一個物理機(jī)上(因?yàn)槿绻嬖谝粋€機(jī)器上振诬,副本的高可用性就沒有了)
swapping是性能的墳?zāi)?/p>
這是顯而易見的蹭睡,但是還是有必要說的更清楚一點(diǎn),內(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要好停局,因?yàn)樵谝恍﹥?nèi)核版本,swappness=0會引發(fā)OOM(內(nèi)存溢出)
最后香府,如果上面的方法都不能做到董栽,你需要打開配置文件中的mlockall開關(guān),它的作用就是運(yùn)行JVM鎖住內(nèi)存企孩,禁止OS交換出去锭碳。在elasticsearch.yml配置如下:
bootstrap.mlockall: true