ElasticSearch性能優(yōu)化

ElasticSearch在性能優(yōu)化上分為兩大部分,一個(gè)是單機(jī)的參數(shù)優(yōu)化(這個(gè)占大部分),另一個(gè)是集群的設(shè)置,集群從一定程度上可以看做是多個(gè)單機(jī)組成的,所以它的調(diào)試偏向于集群配置。

寫在前面:

我們針對(duì)于每個(gè)點(diǎn)的調(diào)試只說一點(diǎn),因?yàn)楣俜轿臋n敘述的太繁多,無關(guān)緊要的項(xiàng)沒必要全列出來,有興趣的可以自行參考,具體的設(shè)置是否開啟,開啟比例等需要根據(jù)業(yè)務(wù)場(chǎng)景來衡量。

分片數(shù)

ES數(shù)據(jù)存在索引中,一個(gè)索引由多個(gè)分片組成,每個(gè)查詢?cè)诿總€(gè)分片的單個(gè)線程中執(zhí)行,也就是可以并行處理多個(gè)分片,對(duì)同一分片也可以進(jìn)行多個(gè)查詢和聚合。
所以我們可以適當(dāng)?shù)臑槊總€(gè)索引設(shè)置合理的分片數(shù),來提高查詢的并行能力,以此來提高速度
ES中默認(rèn)是5個(gè)分片

案例:400G的索引文件默認(rèn)分片下,聚合全部數(shù)據(jù)的一個(gè)字段需要4~5s,分片數(shù)提升到20片,速度在1s內(nèi)。

JVM內(nèi)存值設(shè)置

Elasticsearch通過 jvm.options文件中的XmsXmx來設(shè)置大小內(nèi)存

-Xms2g
-Xmx2g

注意:這個(gè)內(nèi)存并非是越大越好

由于JVM自帶了zero-based compressed oops(零基壓縮優(yōu)化):

從JDK 1.6 update14開始,64 bit JVM正式支持了 -XX:+UseCompressedOops ,這個(gè)可以壓縮指針,起到節(jié)約內(nèi)存占用的新參數(shù)。
Compressed OOPS,即對(duì)象壓縮技術(shù),壓縮引用到32位,以降低堆的占用空間。Zero Based Compressed OOPS(零基壓縮優(yōu)化)進(jìn)一步提高了壓解壓效率。

但是在超過臨界值32G內(nèi)存時(shí),這個(gè)優(yōu)化策略將會(huì)失效,通常64位JVM消耗的內(nèi)存會(huì)比32位的大1.5倍,這是因?yàn)閷?duì)象指針在64位架構(gòu)下,長(zhǎng)度會(huì)翻倍(事實(shí)上當(dāng)內(nèi)存到達(dá)40-50GB的時(shí)候,有效內(nèi)存才相當(dāng)于使用Compressed OOPS技術(shù)時(shí)候的32G內(nèi)存)

所以,一般設(shè)置到32G就可以。

禁止Swap(內(nèi)存交換)

大多數(shù)操作系統(tǒng)都試圖盡可能多地使用文件系統(tǒng)緩存,并急切地交換未使用的應(yīng)用程序內(nèi)存,可以通俗的理解為:

swap=內(nèi)存與硬盤交換數(shù)據(jù)

這種操作對(duì)于性能和節(jié)點(diǎn)的穩(wěn)定性都是非常不利的,它會(huì)導(dǎo)致垃圾收集持續(xù)數(shù)分鐘而不是毫秒,并且會(huì)導(dǎo)致節(jié)點(diǎn)響應(yīng)緩慢甚至斷開與集群的連接。
有三種方法來設(shè)置swap

停掉本機(jī)所有swap
sudo swapoff -a  
降低swappiness優(yōu)先級(jí)
sudo sysctl vm.swappiness = 1  
針對(duì)elasticsearch.yml設(shè)置內(nèi)存lock
bootstrap.memory_lock: true

三種方法對(duì)應(yīng)著三種不同范圍的定義,權(quán)限和范圍都是是由大到小,可根據(jù)服務(wù)器的功能靈活配置。

去掉mapping中_all域

Index中默認(rèn)會(huì)有_all的域,這個(gè)會(huì)給查詢帶來方便,但是會(huì)增加索引時(shí)間和索引數(shù)據(jù)大小

PUT my_index
{
  "mappings": {
    "type_2": {
      "_all": {
        "enabled": false
      },
      "properties": {...}
    }
  }
}

Cache比例

Indices Cache

索引緩存,用于插數(shù)據(jù)時(shí)

indices.memory.index_buffer_size: 10%
Node Query Cache

節(jié)點(diǎn)查詢緩存查詢,負(fù)責(zé)緩存查詢結(jié)果。每個(gè)Node上的所有shards都共享一個(gè)查詢緩存(只針對(duì)filter緩存)。緩存實(shí)現(xiàn)了LRU驅(qū)逐策略;

常用的三種緩存驅(qū)逐策略:

1.LRU:最近最少使用的,緩存的元素有一個(gè)時(shí)間戳,當(dāng)緩存容量滿了,而又需要騰出地方來緩存新的元素的時(shí)候,那么現(xiàn)有緩存元素中時(shí)間戳離當(dāng)前時(shí)間最遠(yuǎn)的元素將被清除緩存。
2.LFU:最少被使用,緩存的元素有一個(gè)hit屬性,hit值最小的將會(huì)被清除緩存。
3.FIFO:先進(jìn)先出。

es采用了LRU驅(qū)逐策略

設(shè)置Node查詢緩存的值,可以在每個(gè)Node上單獨(dú)設(shè)置

indices.queries.cache.size:5%
Fielddata Cache

Fielddata Cache主要應(yīng)用在text類型的字段上,是一個(gè)永久存在于堆中的緩存,fielddata 會(huì)加載索引中(針對(duì)該特定字段的) 所有的文檔,它會(huì)消耗大量的堆內(nèi)存,可以在elasticsearch.yml里設(shè)置

indices.fielddata.cache.size:60%

由于Fielddata 耗費(fèi)內(nèi)存嚴(yán)重但是效率高,所以針對(duì)特殊業(yè)務(wù)場(chǎng)景,可以配置使用。
Fielddata :https://www.elastic.co/guide/en/elasticsearch/reference/6.4/fielddata.html

批量和并發(fā)操作

批量操作

批量操作優(yōu)于單個(gè)請(qǐng)求的效率,所以盡可能多的使用批量操作。
但是這里需要大致找到批量請(qǐng)求的最佳大小,一個(gè)通用的方法是在具有單個(gè)分片的單個(gè)節(jié)點(diǎn)上運(yùn)行基準(zhǔn)測(cè)試。 首先嘗試索引100個(gè)文件,然后是200,然后是400,等等。 當(dāng)索引速度開始穩(wěn)定時(shí),我們便知道達(dá)到了數(shù)據(jù)批量請(qǐng)求的最佳大小。

java批量API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-bulk.html

并發(fā)操作

單個(gè)線程發(fā)送批量請(qǐng)求不太可能將Elasticsearch集群的性能最大化利用,為了發(fā)揮Elasticsearch集群的最大性能,應(yīng)該從多個(gè)線程或進(jìn)程發(fā)送我們的業(yè)務(wù)請(qǐng)求。 除了更好地利用集群的資源,這應(yīng)該有助于降低每個(gè)fsync的成本。

注意:TOO_MANY_REQUESTS(429)響應(yīng)代碼(Java客戶端的EsRejectedExecutionException),這是Elasticsearch告訴我們承受不住這么高頻率的請(qǐng)求了。

與批量調(diào)整大小請(qǐng)求類似,只有測(cè)試才能確定最佳的并發(fā)數(shù)量。 這可以通過逐漸增加工作者數(shù)量來測(cè)試,直到集群上的I / OCPU飽和。

調(diào)整index.refresh_interval

Elasticsearch 在寫入數(shù)據(jù)時(shí)候,采用延遲寫入的策略,即數(shù)據(jù)先寫到內(nèi)存中,當(dāng)超過默認(rèn) 1 秒 (index.refresh_interval)會(huì)進(jìn)行一次寫入操作,就是將內(nèi)存中 segment 數(shù)據(jù)刷新到操作系統(tǒng)中,此時(shí)我們才能將數(shù)據(jù)搜索出來,所以這就是為什么 Elasticsearch 提供的是近實(shí)時(shí)搜索功能,而不是實(shí)時(shí)搜索功能。

index.refresh_interval默認(rèn)是1s,

經(jīng)常執(zhí)行刷新合并操作,這使得對(duì)搜索可見的索引進(jìn)行最近的更改。但是也頻繁使用了服務(wù)器性能,可以把改參數(shù)設(shè)置為不刷新或者合適的時(shí)間間隔

禁用刷新
index.refresh_interval:-1
擴(kuò)大刷新時(shí)間
index.refresh_interval:60s

優(yōu)化es的線程池

最新版本的es線程池有三種類型:

cache:這是無限制的線程池,為每個(gè)傳入的請(qǐng)求創(chuàng)建一個(gè)線程。
fixed:這是一個(gè)有著固定大小的線程池,大小由size屬性指定,允許你指定一個(gè)隊(duì)列(使用queue_size屬性指定)用來保存請(qǐng)求,直到有一個(gè)空閑的線程來執(zhí)行請(qǐng)求。如果Elasticsearch無法把請(qǐng)求放到隊(duì)列中(隊(duì)列滿了),該請(qǐng)求將被拒絕。
scaling:縮放線程池?fù)碛袆?dòng)態(tài)線程數(shù)。這個(gè)數(shù)字與工作量成正比,并且在核心值和最大值之間變化。

可指定線程池類型的操作

index:此線程池用于索引和刪除操作。默認(rèn)type為fixed,size為可用處理器的數(shù)量,size為300。
search:此線程池用于搜索和計(jì)數(shù)請(qǐng)求。默認(rèn)type為fixed,size為可用處理器的數(shù)量乘以3,size為1000。

get:此線程池用于實(shí)時(shí)的GET請(qǐng)求。默認(rèn)為fixed,size為可用處理器的數(shù)量,size默認(rèn)為1000。
bulk:此線程池用于批量操作。默認(rèn)為fixed,size為可用處理器的數(shù)量,size為50。

......
......

elasticsearch.yml中可以設(shè)置 :

threadpool.index.type: fixed
threadpool.index.size: 100
threadpool.index.queue_size: 500
thread_pool.get.queue_size
thread_pool.bulk.queue_size
thread_pool.index.queue_size
thread_pool.listener.queue_size
thread_pool.search.queue_size
thread_pool.force_merge.queue_size

G1垃圾回收機(jī)制代替默認(rèn)CMS

cms和g1的區(qū)別可以參考http://www.itdecent.cn/p/466068ce238d
替換方式為把elasticsearch.in.sh 文件內(nèi)將

if [ "x$ES_USE_IPV4" != "x" ]; then
  JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
fi
 
JAVA_OPTS="$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=75"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly"

替換為

JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=200"

以上就是ElasticSearch性能優(yōu)化的一些關(guān)鍵點(diǎn),后續(xù)發(fā)現(xiàn)歡迎補(bǔ)充

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

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