Elasticsearch優化方案

關於Lucene:html

ApacheLucene將寫入索引的全部信息組織成一種倒排索引(Inverted Index)的結構之中,該結構是種將詞項映射到文檔的數據結構。其工做方式與傳統的關係數據庫不一樣,大體來講倒排索引是面向詞項而不是面向文檔的。且Lucene索引之中還存儲了不少其餘的信息,如詞向量等等,每一個Lucene都是由多個段構成的,每一個段只會被建立一次但會被查詢屢次,段一旦建立就不會再被修改。多個段會在段合併的階段合併在一塊兒,什麼時候合併由Lucene的內在機制決定,段合併後數量會變少,可是相應的段自己會變大。段合併的過程是很是消耗I/O的,且與之同時會有些再也不使用的信息被清理掉。在Lucene中,將數據轉化爲倒排索引,將完整串轉化爲可用於搜索的詞項的過程叫作分析。文本分析由分析器(Analyzer)來執行,分析其由分詞器(Tokenizer),過濾器(Filter)和字符映射器(Character Mapper)組成,其各個功能顯而易見。除此以外,Lucene有本身的一套完整的查詢語言來幫助咱們進行搜索和讀寫。java

 

 [注]ES中的索引指的是查詢/尋址時URI中的一個字段如:[host]:[port(9200)]/[index]/[type]/[ID]?[option],而Lucene中的索引更多地和ES中的分片的概念相對應。數據庫

 

回到ElasticSearch,ES的架構遵循的設計理念有如下幾個特徵:bootstrap

 

1. 合理的默認配置:只需修改節點中的Yaml配置文件,就能夠迅捷配置。這和Spring4中對配置的簡化有類似的地方。網絡

2. 分佈式工做模式:ES強大的Zen發現機制不只支持組廣播也支持點單播,且有「知一點即知天下」之妙。數據結構

3. 對等架構:節點之間自動備份分片,且使分片自己和樣本之間儘可能」遠離「,能夠避免單點故障。且Master節點和Data節點幾乎徹底等價。架構

4. 易於向集羣擴充新節點:大大簡化研發或運維將新節點加入集羣所需的工做。oracle

5. 不對索引中的數據結構增長任何限制:ES支持在一個索引之中存在多種數據類型。app

6. 準實時:搜索和版本同步,因爲ES是分佈式應用,一個重大的挑戰就是一致性問題,不管索引仍是文檔數據,然而事實證實ES表現優秀。運維

 

 

(一)分片策略

 

選擇合適的分片數和副本數。ES的分片分爲兩種,主分片(Primary Shard)和副本(Replicas)。默認狀況下,ES會爲每一個索引建立5個分片,即便是在單機環境下,這種冗餘被稱做過分分配(Over Allocation),目前看來這麼作徹底沒有必要,僅在散佈文檔到分片和處理查詢的過程當中就增長了更多的複雜性,好在ES的優秀性能掩蓋了這一點。假設一個索引由一個分片構成,那麼當索引的大小超過單個節點的容量的時候,ES不能將索引分割成多份,所以必須在建立索引的時候就指定好須要的分片數量。此時咱們所能作的就是建立一個新的索引,並在初始設定之中指定這個索引擁有更多的分片。反之若是過分分配,就增大了Lucene在合併分片查詢結果時的複雜度,從而增大了耗時,因此咱們獲得瞭如下結論:

咱們應該使用最少的分片!

主分片,副本和節點最大數之間數量存在如下關係:

節點數<=主分片數*(副本數+1)

 

 控制分片分配行爲。以上是在建立每一個索引的時候須要考慮的優化方法,然而在索引已建立好的前提下,是否就是沒有辦法從分片的角度提升了性能了呢?固然不是,首先能作的是調整分片分配器的類型,具體是在elasticsearch.yml中設置cluster.routing.allocation.type屬性,共有兩種分片器even_shard,balanced(默認)。even_shard是儘可能保證每一個節點都具備相同數量的分片,balanced是基於可控制的權重進行分配,相對於前一個分配器,它更暴漏了一些參數而引入調整分配過程的能力。

每次ES的分片調整都是在ES上的數據分佈發生了變化的時候進行的,最有表明性的就是有新的數據節點加入了集羣的時候。固然調整分片的時機並非由某個閾值觸發的,ES內置十一個裁決者來決定是否觸發分片調整,這裏暫不贅述。另外,這些分配部署策略都是能夠在運行時更新的,更多配置分片的屬性也請你們自行Google。

 

 

(二)路由優化

 

ES中所謂的路由和IP網絡不一樣,是一個相似於Tag的東西。在建立文檔的時候,能夠經過字段爲文檔增長一個路由屬性的Tag。ES內在機制決定了擁有相同路由屬性的文檔,必定會被分配到同一個分片上,不管是主分片仍是副本。那麼,在查詢的過程當中,一旦指定了感興趣的路由屬性,ES就能夠直接到相應的分片所在的機器上進行搜索,而避免了複雜的分佈式協同的一些工做,從而提高了ES的性能。於此同時,假設機器1上存有路由屬性A的文檔,機器2上存有路由屬性爲B的文檔,那麼我在查詢的時候一旦指定目標路由屬性爲A,即便機器2故障癱瘓,對機器1構不成很大影響,因此這麼作對災況下的查詢也提出瞭解決方案。所謂的路由,本質上是一個分桶(Bucketing)操做。固然,查詢中也能夠指定多個路由屬性,機制大同小異。

 

 

(三)ES上的GC調優

 

ElasticSearch本質上是個Java程序,因此配置JVM垃圾回收器自己也是一個頗有意義的工做。咱們使用JVM的Xms和Xmx參數來提供指定內存大小,本質上提供的是JVM的堆空間大小,當JVM的堆空間不足的時候就會觸發致命的OutOfMemoryException。這意味着要麼內存不足,要麼出現了內存泄露。處理GC問題,首先要肯定問題的源頭,通常有兩種方案:

 

1. 開啓ElasticSearch上的GC日誌

2. 使用jstat命令

3. 生成內存Dump

 

關於第一條,在ES的配置文件elasticsearch.yml中有相關的屬性能夠配置,關於每一個屬性的用途這裏固然說不完。

第二條,jstat命令能夠幫助咱們查看JVM堆中各個區的使用狀況和GC的耗時狀況。

第三條,最後的辦法就是將JVM的堆空間轉儲到文件中去,實質上是對JVM堆空間的一個快照。

想了解更多關於JVM自己GC調優方法請參考:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

另外,經過修改ES節點的啓動參數,也能夠調整GC的方式,可是實質上和上述方法是等同的。

 

 

(四)避免內存交換

 

這一點很簡單,因爲操做系統的虛擬內存頁交換機制,會給性能帶來障礙,如數據寫滿內存會寫入Linux中的Swap分區。

能夠經過在elasticsearch.yml文件中的bootstrap.mlockall設置爲true來實現,可是須要管理員權限,須要修改操做系統的相關配置文件。

 

 

(五)控制索引合併

 

上文提到過,ES中的分片和副本本質上都是Lucene索引,而Lucene索引又基於多個索引段構建(至少一個),索引文件中的絕大多數都是隻被寫一次,讀屢次,在Lucene內在機制控制下,當知足某種條件的時候多個索引段會被合併到一個更大的索引段,而那些舊的索引段會被拋棄並移除磁盤,這個操做叫作段合併。 

Lucene要執行段合併的理由很簡單充分:索引段粒度越小,查詢性能越低且耗費的內存越多。頻繁的文檔更改操做會致使大量的小索引段,從而致使文件句柄打開過多的問題,如修改系統配置,增大系統容許的最大文件打開數。總的來說,當索引段由多一個合併爲一個的時候,會減小索引段的數量從而提升ES性能。對於研發者來說,咱們所能作的就是選擇合適的合併策略,儘管段合併徹底是Lucene的任務,但隨着Lucene開放更多配置藉口,新版本的ES仍是提供了三種合併的策略tiered,log_byte_size,log_doc。另外,ES也提供了兩種Lucene索引段合併的調度器:concurrent和serial。其中各者具體區別,這裏暫不贅述,只是拋磚引玉。

相關文章
相關標籤/搜索