关于ElasticSearch性能调优几件必须知道的事
(零)ElasticSearch架構(gòu)概述
?
ElasticSearch是現(xiàn)在技術(shù)前沿的大數(shù)據(jù)引擎,常見的組合有ES+Logstash+Kibana作為一套成熟的日志系統(tǒng),其中Logstash是ETL工具,Kibana是數(shù)據(jù)分析展示平臺。ES讓人驚艷的是他強大的搜索相關(guān)能力和災(zāi)備策略,ES開放了一些接口供開發(fā)者研發(fā)自己的插件,ES結(jié)合中文分詞的插件會給ES的搜索和分析起到很大的推動作用。ElasticSearch是使用開源全文檢索庫ApacheLucene進行索引和搜索的,說架構(gòu)必須和Lucene的一些東西打交道。
?
關(guān)于Lucene:
ApacheLucene將寫入索引的所有信息組織成一種倒排索引(Inverted Index)的結(jié)構(gòu)之中,該結(jié)構(gòu)是種將詞項映射到文檔的數(shù)據(jù)結(jié)構(gòu)。其工作方式與傳統(tǒng)的關(guān)系數(shù)據(jù)庫不同,大致來說倒排索引是面向詞項而不是面向文檔的。且Lucene索引之中還存儲了很多其他的信息,如詞向量等等,每個Lucene都是由多個段構(gòu)成的,每個段只會被創(chuàng)建一次但會被查詢多次,段一旦創(chuàng)建就不會再被修改。多個段會在段合并的階段合并在一起,何時合并由Lucene的內(nèi)在機制決定,段合并后數(shù)量會變少,但是相應(yīng)的段本身會變大。段合并的過程是非常消耗I/O的,且與之同時會有些不再使用的信息被清理掉。在Lucene中,將數(shù)據(jù)轉(zhuǎn)化為倒排索引,將完整串轉(zhuǎn)化為可用于搜索的詞項的過程叫做分析。文本分析由分析器(Analyzer)來執(zhí)行,分析其由分詞器(Tokenizer),過濾器(Filter)和字符映射器(Character Mapper)組成,其各個功能顯而易見。除此之外,Lucene有自己的一套完整的查詢語言來幫助我們進行搜索和讀寫。
?
?[注]ES中的索引指的是查詢/尋址時URI中的一個字段如:[host]:[port(9200)]/[index]/[type]/[ID]?[option],而Lucene中的索引更多地和ES中的分片的概念相對應(yīng)。
?
回到ElasticSearch,ES的架構(gòu)遵循的設(shè)計理念有以下幾個特征:
?
1.?合理的默認(rèn)配置:只需修改節(jié)點中的Yaml配置文件,就可以迅捷配置。這和Spring4中對配置的簡化有相似的地方。
2.?分布式工作模式:ES強大的Zen發(fā)現(xiàn)機制不僅支持組廣播也支持點單播,且有“知一點即知天下”之妙。
3.?對等架構(gòu):節(jié)點之間自動備份分片,且使分片本身和樣本之間盡量”遠離“,可以避免單點故障。且Master節(jié)點和Data節(jié)點幾乎完全等價。
4.?易于向集群擴充新節(jié)點:大大簡化研發(fā)或運維將新節(jié)點加入集群所需的工作。
5.?不對索引中的數(shù)據(jù)結(jié)構(gòu)增加任何限制:ES支持在一個索引之中存在多種數(shù)據(jù)類型。
6.?準(zhǔn)實時:搜索和版本同步,由于ES是分布式應(yīng)用,一個重大的挑戰(zhàn)就是一致性問題,無論索引還是文檔數(shù)據(jù),然而事實證明ES表現(xiàn)優(yōu)秀。
?
?
(一)分片策略
?
選擇合適的分片數(shù)和副本數(shù)。ES的分片分為兩種,主分片(Primary Shard)和副本(Replicas)。默認(rèn)情況下,ES會為每個索引創(chuàng)建5個分片,即使是在單機環(huán)境下,這種冗余被稱作過度分配(Over Allocation),目前看來這么做完全沒有必要,僅在散布文檔到分片和處理查詢的過程中就增加了更多的復(fù)雜性,好在ES的優(yōu)秀性能掩蓋了這一點。假設(shè)一個索引由一個分片構(gòu)成,那么當(dāng)索引的大小超過單個節(jié)點的容量的時候,ES不能將索引分割成多份,因此必須在創(chuàng)建索引的時候就指定好需要的分片數(shù)量。此時我們所能做的就是創(chuàng)建一個新的索引,并在初始設(shè)定之中指定這個索引擁有更多的分片。反之如果過度分配,就增大了Lucene在合并分片查詢結(jié)果時的復(fù)雜度,從而增大了耗時,所以我們得到了以下結(jié)論:
我們應(yīng)該使用最少的分片!
主分片,副本和節(jié)點最大數(shù)之間數(shù)量存在以下關(guān)系:
節(jié)點數(shù)<=主分片數(shù)*(副本數(shù)+1)
?
?控制分片分配行為。以上是在創(chuàng)建每個索引的時候需要考慮的優(yōu)化方法,然而在索引已創(chuàng)建好的前提下,是否就是沒有辦法從分片的角度提高了性能了呢?當(dāng)然不是,首先能做的是調(diào)整分片分配器的類型,具體是在elasticsearch.yml中設(shè)置cluster.routing.allocation.type屬性,共有兩種分片器even_shard,balanced(默認(rèn))。even_shard是盡量保證每個節(jié)點都具有相同數(shù)量的分片,balanced是基于可控制的權(quán)重進行分配,相對于前一個分配器,它更暴漏了一些參數(shù)而引入調(diào)整分配過程的能力。
每次ES的分片調(diào)整都是在ES上的數(shù)據(jù)分布發(fā)生了變化的時候進行的,最有代表性的就是有新的數(shù)據(jù)節(jié)點加入了集群的時候。當(dāng)然調(diào)整分片的時機并不是由某個閾值觸發(fā)的,ES內(nèi)置十一個裁決者來決定是否觸發(fā)分片調(diào)整,這里暫不贅述。另外,這些分配部署策略都是可以在運行時更新的,更多配置分片的屬性也請大家自行Google。
?
?
(二)路由優(yōu)化
?
ES中所謂的路由和IP網(wǎng)絡(luò)不同,是一個類似于Tag的東西。在創(chuàng)建文檔的時候,可以通過字段為文檔增加一個路由屬性的Tag。ES內(nèi)在機制決定了擁有相同路由屬性的文檔,一定會被分配到同一個分片上,無論是主分片還是副本。那么,在查詢的過程中,一旦指定了感興趣的路由屬性,ES就可以直接到相應(yīng)的分片所在的機器上進行搜索,而避免了復(fù)雜的分布式協(xié)同的一些工作,從而提升了ES的性能。于此同時,假設(shè)機器1上存有路由屬性A的文檔,機器2上存有路由屬性為B的文檔,那么我在查詢的時候一旦指定目標(biāo)路由屬性為A,即使機器2故障癱瘓,對機器1構(gòu)不成很大影響,所以這么做對災(zāi)況下的查詢也提出了解決方案。所謂的路由,本質(zhì)上是一個分桶(Bucketing)操作。當(dāng)然,查詢中也可以指定多個路由屬性,機制大同小異。
?
?
(三)ES上的GC調(diào)優(yōu)
?
ElasticSearch本質(zhì)上是個Java程序,所以配置JVM垃圾回收器本身也是一個很有意義的工作。我們使用JVM的Xms和Xmx參數(shù)來提供指定內(nèi)存大小,本質(zhì)上提供的是JVM的堆空間大小,當(dāng)JVM的堆空間不足的時候就會觸發(fā)致命的OutOfMemoryException。這意味著要么內(nèi)存不足,要么出現(xiàn)了內(nèi)存泄露。處理GC問題,首先要確定問題的源頭,一般有兩種方案:
?
1. 開啟ElasticSearch上的GC日志
2. 使用jstat命令
3. 生成內(nèi)存Dump
?
關(guān)于第一條,在ES的配置文件elasticsearch.yml中有相關(guān)的屬性可以配置,關(guān)于每個屬性的用途這里當(dāng)然說不完。
第二條,jstat命令可以幫助我們查看JVM堆中各個區(qū)的使用情況和GC的耗時情況。
第三條,最后的辦法就是將JVM的堆空間轉(zhuǎn)儲到文件中去,實質(zhì)上是對JVM堆空間的一個快照。
想了解更多關(guān)于JVM本身GC調(diào)優(yōu)方法請參考:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
另外,通過修改ES節(jié)點的啟動參數(shù),也可以調(diào)整GC的方式,但是實質(zhì)上和上述方法是等同的。
?
?
(四)避免內(nèi)存交換
?
這一點很簡單,由于操作系統(tǒng)的虛擬內(nèi)存頁交換機制,會給性能帶來障礙,如數(shù)據(jù)寫滿內(nèi)存會寫入Linux中的Swap分區(qū)。
可以通過在elasticsearch.yml文件中的bootstrap.mlockall設(shè)置為true來實現(xiàn),但是需要管理員權(quán)限,需要修改操作系統(tǒng)的相關(guān)配置文件。
?
?
(五)控制索引合并
?
上文提到過,ES中的分片和副本本質(zhì)上都是Lucene索引,而Lucene索引又基于多個索引段構(gòu)建(至少一個),索引文件中的絕大多數(shù)都是只被寫一次,讀多次,在Lucene內(nèi)在機制控制下,當(dāng)滿足某種條件的時候多個索引段會被合并到一個更大的索引段,而那些舊的索引段會被拋棄并移除磁盤,這個操作叫做段合并。?
Lucene要執(zhí)行段合并的理由很簡單充分:索引段粒度越小,查詢性能越低且耗費的內(nèi)存越多。頻繁的文檔更改操作會導(dǎo)致大量的小索引段,從而導(dǎo)致文件句柄打開過多的問題,如修改系統(tǒng)配置,增大系統(tǒng)允許的最大文件打開數(shù)??偟膩碇v,當(dāng)索引段由多一個合并為一個的時候,會減少索引段的數(shù)量從而提高ES性能。對于研發(fā)者來講,我們所能做的就是選擇合適的合并策略,盡管段合并完全是Lucene的任務(wù),但隨著Lucene開放更多配置借口,新版本的ES還是提供了三種合并的策略tiered,log_byte_size,log_doc。另外,ES也提供了兩種Lucene索引段合并的調(diào)度器:concurrent和serial。其中各者具體區(qū)別,這里暫不贅述,只是拋磚引玉。
總結(jié)
以上是生活随笔為你收集整理的关于ElasticSearch性能调优几件必须知道的事的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: elasticSearch 安装和 he
- 下一篇: flash怎么给图片添加胶片效果(ffm