Elasticsearch5.2.1集羣搭建,動態加入節點,並添加監控診斷插件

寫在前邊的話

ES5.2.1 集羣部署參考:http://blog.csdn.net/gamer_gyt/article/details/59077189

對於集羣的監控和優化是很重要的一部分,如果想持久維護集羣,單單靠增加物理內存,cpu,硬盤是不夠的,必須通過一些方法來進行優化。


集羣結點角色分配

在之前得文章中我們介紹到es集羣中得三個角色 master ,data,client

master結點:node.master: true node.data: false

該node服務器只作爲一個主節點,但不存儲任何索引數據,該node服務器將使用自身空閒得資源,來協調各種創建索引請求或者查詢請求,將這些請求合理分發到相關得node服務器上。

data結點:node.master: false node.data: true

該node服務器只作爲一個數據節點,只用於存儲索引數據。使該node服務器功能 單一,只用於數據存儲和數據查詢,降低其資源消耗率。

client結點(負載均衡結點):node.master: false node.data: false

該node服務器即不會被選作主節點,也不會存儲任何索引數據。該服務器主要用 於查詢負載均衡。在查詢的時候,通常會涉及到從多個node服務器上查詢數據,並請 求分發到多個指定的node服務器,並對各個node服務器返回的結果進行一個彙總處理, 最終返回給客戶端。

1:關閉data結點得http功能

    針對ElasticSearch集羣中的所有數據節點,不用開啓http服務。將其中的配置 參數這樣設置:http.enabled: false,同時也不要安裝head, bigdesk, marvel等監控 插件,這樣保證data節點服務器只需處理創建/更新/刪除/查詢索引數據等操作。

    http功能可以在非數據節點服務器上開啓,上述相關的監控插件也安裝到這些服 務器上,用於監控ElasticSearch集羣狀態等數據信息。這樣做一來出於數據安全考慮,二來出於服務性能考慮。

2:一臺服務器上最好只部署一個node

    一臺物理服務器上可以啓動多個Node服務器節點(通過設置不同的啓動port),但一臺服務器上的CPU,內存,硬盤等資源畢竟有限,從服務器性能考慮,不建議一臺服務器上啓動多個node節點。

    在大規模局點,比如100個點,可以專門配備3個Master,可使用3臺具有內存的刀片即可,即參數配置爲node.master: true,node.data: false;可以按比例配備數據匯聚節點,比如10個,即參數配置爲node.master: false ,node.data: false;小規模節點,可以不用如此設置,當然如果依然有性能問題,也是一個優化的措施


集羣得機器內存設置

    Elasticsearch 默認採用的是Lucene,至於爲什麼es採用這個,原因可能是因爲Lucene是一個成熟的、高性能的、可擴展的、輕量級的,而且功能強大的搜索引擎包。Lucene的核心jar包只有一個文件,而且不依賴任何第三方jar包。更重要的是,它提供的索引數據和檢索數據的功能開箱即用。當然,Lucene也提供了多語言支持,具有拼寫檢查、高亮等功能。當然es使用Lucene作爲分詞搜索包,勢必會造成很大程度上的內存消耗。

1:預留一半內存給Lucene使用

    一個常見的問題是配置堆太大。你有一個64 GB的機器,覺得JVM內存越大越好,想給Elasticsearch所有64 GB的內存。

    當然,內存對於Elasticsearch來說絕對是重要的,用於更多的內存數據提供更快的操作。而且還有一個內存消耗大戶-Lucene

    Lucene的設計目的是把底層OS裏的數據緩存到內存中。Lucene的段是分別存儲到單個文件中的,這些文件都是不會變化的,所以很利於緩存,同時操作系統也會把這些段文件緩存起來,以便更快的訪問。

    Lucene的性能取決於和OS的交互,如果你把所有的內存都分配給Elasticsearch,不留一點給Lucene,那你的全文檢索性能會很差的。

    最後標準的建議是把50%的內存給elasticsearch,剩下的50%也不會沒有用處的,Lucene會很快吞噬剩下的這部分內存。

2:32GB限制

    在java中,所有的對象都分配在堆上,然後有一個指針引用它。指向這些對象的指針大小通常是CPU的字長的大小,不是32bit就是64bit,這取決於你的處理器,指針指向了你的值的精確位置。

    對於32位系統,你的內存最大可使用4G。對於64系統可以使用更大的內存。但是64位的指針意味着更大的浪費,因爲你的指針本身大了。浪費內存不算,更糟糕的是,更大的指針在主內存和緩存器(例如LLC, L1等)之間移動數據的時候,會佔用更多的帶寬。

    java 使用一個叫內存指針壓縮的技術來解決這個問題。它的指針不再表示對象在內存中的精確位置,而是表示偏移量。這意味着32位的指針可以引用40億個對象,而不是40億個字節。最終,也就是說堆內存長到32G的物理內存,也可以用32bit的指針表示。

    一旦你越過那個神奇的30-32G的邊界,指針就會切回普通對象的指針,每個對象的指針都變長了,就會使用更多的CPU內存帶寬,也就是說你實際上失去了更多的內存。事實上當內存到達40-50GB的時候,有效內存才相當於使用內存對象指針壓縮技術時候的32G內存。

    這段描述的意思就是說:即便你有足夠的內存,也儘量不要超過32G,因爲它浪費了內存,降低了CPU的性能,還要讓GC應對大內存。

3:機器內存大於64GB

    你可以考慮一臺機器上創建兩個或者更多ES節點,而不要部署一個使用32+GB內存的節點。仍然要 堅持50%原則,假設 你有個機器有128G內存,你可以創建兩個node,使用32G內存。也就是說64G內存給ES的堆內存,剩下的64G給Lucene。 
    如果你選擇第二種,你需要配置

cluster.routing.allocation.same_shard.host:true

這會防止同一個shard的主副本存在同一個物理機上(因爲如果存在一個機器上,副本的高可用性就沒有了)

4:ES集羣的heap參數優化

    所謂的heap即數據緩存的內存大小,ES集羣中消耗內存的有以下幾個:

1):segment Memory

    Lucene 把每次生成的倒排索引,叫做一個段(segment)。然後另外使用一個 commit 文件,記錄索引內所有的 segment。而生成 segment 的數據來源,則是內存中的 buffer。由於詞典的size會很大,全部裝載到heap裏不現實,因此Lucene爲詞典做了一層前綴索引(Term Index),這個索引在Lucene4.0以後採用的數據結構是FST (Finite State Transducer)。這種數據結構佔用空間很小,Lucene打開索引的時候將其全量裝載到內存中,加快磁盤上詞典查詢速度的同時減少隨機磁盤訪問次數。所以ES的data node存儲數據並非只是耗費磁盤空間的,爲了加速數據的訪問,每個segment都有會一些索引數據駐留在heap裏。因此segment越多,瓜分掉的heap也越多,並且這部分heap是無法被GC掉的! 理解這點對於監控和管理集羣容量很重要,當一個node的segment memory佔用過多的時候,就需要考慮刪除、歸檔數據,或者擴容了。

2):Filter Cache

    Filter cache是用來緩存使用過的filter的結果集的,需要注意的是這個緩存也是常駐heap,無法GC的。默認的10% heap size設置工作得夠好了,如果實際使用中heap沒什麼壓力的情況下,才考慮加大這個設置。

3):Field Data cache

    對搜索結果做排序或者聚合操作,需要將倒排索引裏的數據進行解析,然後進行一次倒排。在有大量排序、數據聚合的應用場景,可以說field data cache是性能和穩定性的殺手。這個過程非常耗費時間,因此ES2.0以前的版本主要依賴這個cache緩存已經計算過的數據,提升性能。但是由於heap空間有限,當遇到用戶對海量數據做計算的時候,就很容易導致heap吃緊,集羣頻繁GC,根本無法完成計算過程。ES2.0以後,正式默認啓用Doc Values特性(1.x需要手動更改mapping開啓),將field data在indexing time構建在磁盤上,經過一系列優化,可以達到比之前採用field data cache機制更好的性能。因此需要限制對field data cache的使用,最好是完全不用,可以極大釋放heap壓力。這裏需要注意的是,排序、聚合字段必須爲not analyzed。設想如果有一個字段是analyzed過的,排序的實際對象其實是詞典,在數據量很大情況下這種情況非常致命。

4):Bulk Queue

    Bulk Queue是做什麼用的?當所有的bulk thread都在忙,無法響應新的bulk request的時候,將request在內存裏排列起來,然後慢慢清掉。一般來說,Bulk queue不會消耗很多的heap,但是見過一些用戶爲了提高bulk的速度,客戶端設置了很大的併發量,並且將bulk Queue設置到不可思議的大,比如好幾千。這在應對短暫的請求爆發的時候有用,但是如果集羣本身索引速度一直跟不上,設置的好幾千的queue都滿了會是什麼狀況呢? 取決於一個bulk的數據量大小,乘上queue的大小,heap很有可能就不夠用,內存溢出了。一般來說官方默認的thread pool設置已經能很好的工作了,建議不要隨意去“調優”相關的設置,很多時候都是適得其反的效果。

5):Indexing Buffer

    Indexing Buffer是用來緩存新數據,當其滿了或者refresh/flush interval到了,就會以segment file的形式寫入到磁盤。這個參數的默認值是10% heap size。根據經驗,這個默認值也能夠很好的工作,應對很大的索引吞吐量。但有些用戶認爲這個buffer越大吞吐量越高,因此見過有用戶將其設置爲40%的。到了極端的情況,寫入速度很高的時候,40%都被佔用,導致OOM。

6):Cluster State Buffer

    ES被設計成每個Node都可以響應用戶的api請求,因此每個Node的內存裏都包含有一份集羣狀態的拷貝。這個Cluster state包含諸如集羣有多少個Node,多少個index,每個index的mapping是什麼?有少shard,每個shard的分配情況等等(ES有各類stats api獲取這類數據)。在一個規模很大的集羣,這個狀態信息可能會非常大的,耗用的內存空間就不可忽視了。並且在ES2.0之前的版本,state的更新是由Master Node做完以後全量散播到其他結點的。頻繁的狀態更新都有可能給heap帶來壓力。在超大規模集羣的情況下,可以考慮分集羣並通過tribe node連接做到對用戶api的透明,這樣可以保證每個集羣裏的state信息不會膨脹得過大。

7):超大搜索聚合結果集的fetch

    ES是分佈式搜索引擎,搜索和聚合計算除了在各個data node並行計算以外,還需要將結果返回給彙總節點進行彙總和排序後再返回。無論是搜索,還是聚合,如果返回結果的size設置過大,都會給heap造成很大的壓力,特別是數據匯聚節點。

5:優化建議:

一般分配主機1/4-1/2的內存 
編輯:elasticsearch/bin/ elasticsearch 
加上(10g換成你自己設置的內存數):

ES_MIN_MEM=10g 
ES_MAX_MEM=10g 
ES_HEAP_NEWSIZE=1g


集羣的硬盤和CPU設置

1:硬盤選型:

    硬盤對集羣非常重要,特別是建索引多的情況。磁盤是一個服務器最慢的系統,對於寫比較重的集羣,磁盤很容易成爲集羣的瓶頸。如果可以承擔的器SSD盤,最好使用SSD盤。如果使用SSD,最好調整I/O調度算法。RAID0是加快速度的不錯方法。

2:自動調整存儲帶寬

    在2.0.0之前,elasticsearch會限制合併速度(merges),默認爲20MB/sec。但是這個速率經常是顯得太小,導致合併速度落後於索引速度,進而限制了索引速度。

    現在Elasticsearch2.0.0之後,使用了自動調整合並IO速度方式:如果合併落於索引速度,合併IO速度會逐漸增大,並且隨着合併的持續進行會減小。在索引吞吐量小的時候,即使突然來了一個大的合併任務,這種情況也不會吞噬整個節點可用的IO,極小化的降低對正在進行的查詢和索引的影響。 
但是對索引請求大的情況下,允許的合併速度會自動調整到跟上索引的速度。有了2.0.0這個特性,意味着我們不需要管任何的限制值了,只要用默認的就好了。

3:多個path.data 路徑

    如果磁盤空間和IO性能是Elasticsearch的瓶頸的話,使用多個IO設備(通過設置多個path.data路徑)存儲shards,能夠增加總的存儲空間和提升IO性能。

    在Elasticsearch2.0之前的版本,也是配置多個path.data路徑,但是其相當於RAID 0,每個shards的數據會分佈在所有的磁盤上。當一個節點上有一塊盤壞了的情況下,該節點上所有的shards都會損壞了。需要恢復該節點上的所有shards。

    在2.0.0版本,把這個實現改成了:每個shards所有的數據只會在一塊磁盤上面。這樣即使一個節點的一塊磁盤損壞了,也只是損失了該磁盤上的shards,其它磁盤上的shards安然無事。只需要恢復該塊盤上的shards即可。

    升級到2.0.0版本時,舊版本一個shard分佈到所有磁盤上的數據,會拷貝到一塊盤上。

    對應這個改變,在設計shards時,如果一個節點有10塊磁盤,共3個節點,則shards至少30個,才能分佈在30塊盤上(即最大限度使用磁盤空間)。


集羣的分片和副本配置

分片(Shard)

一個索引會分成多個分片存儲,分片數量在索引建立後不可更改 
分片數是與檢索速度非常相關的的指標,如果分片數過少或過多都會導致檢索比較慢。分片數過多會導致檢索時打開比較多的文件別外也會導致多臺服務器之間通訊。而分片數過少會導致單個分片索引過大,所以檢索速度慢。基於索引分片數=數據總量/單分片數的計算公式,在確定分片數之前需要進行單服務單索引單分片的測試,目前我們測試的結果單個分片的內容爲10G。

副本(replicas)

每個索引的數據備份數量。 
ElasticSearch在創建索引數據時,最好指定相關的shards數量和replicas, 否則會使用服務器中的默認配置參數shards=5,replicas=1。

因爲這兩個屬性的設置直接影響集羣中索引和搜索操作的執行。假設你有足夠的機器來持有碎片和副本,那麼可以按如下規則設置這兩個值:

  • 1) 擁有更多的碎片可以提升索引執行能力,並允許通過機器分發一個大型的索引;
  • 2) 擁有更多的副本能夠提升搜索執行能力以及集羣能力。

對於一個索引來說,number_of_shards只能設置一次,而number_of_replicas可以使用索引更新設置API在任何時候被增加或者減少。

這兩個配置參數在配置文件的配置如下:

index.number_of_shards: 5 
number_of_replicas: 1

Elastic官方文檔建議:一個Node中一個索引最好不要多於三個shards.配置total_shards_per_node參數,限制每個index每個節點最多分配多少個發片.


集羣的優化總結

1:java jdk版本儘量高一點,否則容易出現bug 
2:es集羣結點規劃好,master,client,data node 分開,關閉data node 的http功能 
3:合理利用內存 
4:根據機器數,磁盤數,索引大小等硬件環境,根據測試結果,設置最優的分片數和備份數,單個分片最好不超過10GB,定期刪除不用的索引,做好冷數據的遷移。 
5:保守配置內存限制參數,儘量使用doc value存儲以減少內存消耗,查詢時限制size、from參數。 
6:結合實際場景,做好集羣監控

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章