關(guān)于Lucene:
????????Apache Lucene將寫入索引的所有信息組織成一種倒排索引(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)在機(jī)制決定子姜,段合并后數(shù)量會變少祟绊,但是相應(yīng)的段本身會變大。段合并的過程是非常消耗I/O的闲询,且與之同時會有些不再使用的信息被清理掉久免。在Lucene中浅辙,將數(shù)據(jù)轉(zhuǎn)化為倒排索引扭弧,將完整串轉(zhuǎn)化為可用于搜索的詞項的過程叫做分析。文本分析由分析器(Analyzer)來執(zhí)行记舆,分析其由分詞器(Tokenizer)鸽捻,過濾器(Filter)和字符映射器(Character Mapper)組成,其各個功能顯而易見泽腮。除此之外御蒲,Lucene有自己的一套完整的查詢語言來幫助我們進(jìn)行搜索和讀寫。
ElasticSearch诊赊,ES的架構(gòu)遵循的設(shè)計理念有以下幾個特征:
1.?合理的默認(rèn)配置:只需修改節(jié)點中的Yaml配置文件厚满,就可以迅捷配置。這和Spring4中對配置的簡化有相似的地方碧磅。
2.?分布式工作模式:ES強大的Zen發(fā)現(xiàn)機(jī)制不僅支持組廣播也支持點單播碘箍,且有“知一點即知天下”之妙。
3.?對等架構(gòu):節(jié)點之間自動備份分片鲸郊,且使分片本身和樣本之間盡量”遠(yuǎn)離“丰榴,可以避免單點故障。且Master節(jié)點和Data節(jié)點幾乎完全等價秆撮。
4.?易于向集群擴(kuò)充新節(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個分片,即使是在單機(jī)環(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)重進(jìn)行分配拍屑,相對于前一個分配器,它更暴漏了一些參數(shù)而引入調(diào)整分配過程的能力坑傅。
每次ES的分片調(diào)整都是在ES上的數(shù)據(jù)分布發(fā)生了變化的時候進(jìn)行的僵驰,最有代表性的就是有新的數(shù)據(jù)節(jié)點加入了集群的時候。當(dāng)然調(diào)整分片的時機(jī)并不是由某個閾值觸發(fā)的唁毒,ES內(nèi)置十一個裁決者來決定是否觸發(fā)分片調(diào)整蒜茴,這里暫不贅述。另外浆西,這些分配部署策略都是可以在運行時更新的粉私,更多配置分片的屬性也請大家自行Google。
(二)路由優(yōu)化
ES中所謂的路由和IP網(wǎng)絡(luò)不同近零,是一個類似于Tag的東西诺核。在創(chuàng)建文檔的時候抄肖,可以通過字段為文檔增加一個路由屬性的Tag。ES內(nèi)在機(jī)制決定了擁有相同路由屬性的文檔窖杀,一定會被分配到同一個分片上漓摩,無論是主分片還是副本。那么入客,在查詢的過程中管毙,一旦指定了感興趣的路由屬性,ES就可以直接到相應(yīng)的分片所在的機(jī)器上進(jìn)行搜索桌硫,而避免了復(fù)雜的分布式協(xié)同的一些工作夭咬,從而提升了ES的性能。于此同時铆隘,假設(shè)機(jī)器1上存有路由屬性A的文檔卓舵,機(jī)器2上存有路由屬性為B的文檔,那么我在查詢的時候一旦指定目標(biāo)路由屬性為A咖驮,即使機(jī)器2故障癱瘓边器,對機(jī)器1構(gòu)不成很大影響训枢,所以這么做對災(zāi)況下的查詢也提出了解決方案托修。所謂的路由,本質(zhì)上是一個分桶(Bucketing)操作恒界。當(dāng)然睦刃,查詢中也可以指定多個路由屬性,機(jī)制大同小異十酣。
(三)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)存頁交換機(jī)制须喂,會給性能帶來障礙,如數(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)在機(jī)制控制下宙地,當(dāng)滿足某種條件的時候多個索引段會被合并到一個更大的索引段摔认,而那些舊的索引段會被拋棄并移除磁盤,這個操作叫做段合并宅粥。
Lucene要執(zhí)行段合并的理由很簡單充分:索引段粒度越小参袱,查詢性能越低且耗費的內(nèi)存越多。頻繁的文檔更改操作會導(dǎo)致大量的小索引段秽梅,從而導(dǎo)致文件句柄打開過多的問題抹蚀,如修改系統(tǒng)配置,增大系統(tǒng)允許的最大文件打開數(shù)企垦』啡溃總的來講,當(dāng)索引段由多一個合并為一個的時候钞诡,會減少索引段的數(shù)量從而提高ES性能郑现。對于研發(fā)者來講,我們所能做的就是選擇合適的合并策略臭增,盡管段合并完全是Lucene的任務(wù)懂酱,但隨著Lucene開放更多配置借口,新版本的ES還是提供了三種合并的策略tiered誊抛,log_byte_size列牺,log_doc。另外拗窃,ES也提供了兩種Lucene索引段合并的調(diào)度器:concurrent和serial瞎领。其中各者具體區(qū)別泌辫,這里暫不贅述,只是拋磚引玉九默。