[譯]9條關於高性能ElasticSearch的配置建議

原文連接:https://www.loggly.com/blog/nine-tips-configuring-elasticsearch-for-high-performance/node

Loggy使用ES做爲其不少核心功能的搜索引擎. 如Jon Gifford在最近的文章ElasticSearch vs Solr中所述, 日誌管理系統對搜索引擎有特別需求, 具體以下:bootstrap

  • 對於大規模的數據索引具備可靠的性能及準實時的表現--在咱們場景中,每秒有接近100000條日誌記錄segmentfault

  • 同時對於大量的搜索處理能維護較高的性能和效率.緩存

在構建咱們的Gen2日誌管理服務時, 咱們但願能設置最優的參數以最大程序的發揮ElasticSearch的索引和搜索性能. 不幸的時, 很難在一個地方收集到完善的ElasticSearch設置文檔. 這篇文章總結了咱們學習到的一些知識, 同時能夠做爲你部署和配置本身的ES應用的一個參考列表.安全

本文檔最新更新於09/2016網絡

1: 提早規劃indices, shards和cluster state的增加趨勢

在ES中建立indices和shards很是簡單, 但須要記住的是每一個indiex和shard都有相應的資源開銷.若是有太多的indices和shards, 單單是對他們管理上的開銷就可能大大下降你的ES集羣性能, 甚至極端場景下使服務不可用.數據結構

咱們發現對管理系統開銷影響最大的因素是cluster state, 包含了集羣中每一個索引的mappings信息.曾經某段時間, 咱們單個集羣的cluster state信息佔用了900MB的空間. 集羣雖然還存活着, 但已處於不可用狀態.併發

下面咱們經過一些數據來感覺下其中都發生了事情...app

假設你有一個索引, 其mappings大小爲50K(在咱們的集羣中, 大約有700個字段). 若是你每小時生成一個索引, 那麼一天下來將會有24 x 50K的cluster state數據增量, 大約是1.2MB. 若是你的系統中保存了1年的數據, cluster state信息將達到438MB(8760個indices, 53800個shards). 若是天天一個索引的話, cluster state信息會減小到18.25MB(365個indices, 1825個shards). 能夠看到,每小時一個索引會把你置於一個徹底不一樣的處境.curl

若是你的系統有實時索引數據的需求, 最好先爲之作些規劃, 並清楚的意識到你的系統中會存儲多少cluster state信息以及將包含多少indices和shards. 在部署到生產環境以前, 應該先多作些測試和演練, 避免在凌晨3點因集羣不可用而被叫起.

在集羣配置方面, 爲避免把本身置於險境, 你須要對系統中能容納的indices和shards數量有全面的掌控.

2: 配置以前,先認識集羣拓撲結構

在Loggly, 咱們把ES的master節點和data節點分開部署.如今咱們要說的不是這些細節, 而是強調在你作出正常的配置以前, 先選擇正常的拓撲.

另外, 咱們對於索引請求和查詢請求也使用了不一樣的客戶端程序. 這樣不但能夠爲data節點減輕負載, 更重要的是咱們的執行隊列能夠先提交給本地客戶端, 再由其與集羣的其餘節點交互.

設置節點爲master或data節點由如下兩個參數的值來決定:

Master node: node.master:true node.data:false
Data node: node.master:false node.data:true
Client node: node.master:false node.data:false

上面的部分比較簡單, 下面開始介紹一些須要着重注意的高級屬性. 對於大部分系統來講, ES的默認配置已經足夠, 但若是你的使用場景正如咱們常常看到的日誌類系統, 請必定不要錯過下面的部分.

3: 設置mlockall是提高性能的最有效手段

Linux把它的物理內存劃分爲不少塊, 稱爲. 而Swapping則是把內存中的一頁複製到磁盤上預約義空間的過程, 以釋放更多的內存頁, 而磁盤上的這部分空間稱爲交換區. 物理內存和交換區空間的總和稱爲虛擬內存空間.

交換區並不老是有利的. 由於下內存相比, 磁盤老是慢太多. 一般內存的存儲速度在納秒級, 而磁盤卻要毫秒級別. 因此磁盤的訪問速度比直接訪問內存要慢上萬倍. 使用的交換空間越多, 系統會越多, 因此要避免交換區的使用.

mlockall參數容許設置ES節點不換出內存頁(只有Linux/Unix系統纔有此設置). 在你的yaml文件中, 可經過以下方式設置:

bootstrap.mlockall:true

在5.x版本中, 該參數被bootstrap.memory_lock:true所代替.

默認mlockall的值爲false, 意味着ES節點的內存被容許換出. 設置該屬性值後, 須要重啓ES節點才能生效. 能夠經過以下訪問進行驗證設置是否成功:

curl http://localhost:9200/_nodes/process?pretty

同時要注意, 若是設置了mlockall爲true, 要確認經過-DXmx或ES_HEAP_SIZE給你的ES設置了足夠的堆空間.

4: 經過discovery.zen控制ES的節點發現管理

Zen discovery是ES集羣中節點發現鏈接的默認機制, 另外還有一些其餘的發現機制, 如Azure, EC2和GCE. Zen discovery經過discovery.zen.*的一系列參數進行設置和控制.

在0.x和1.x版本中, 能夠設置單播或多播方式, 而且多播是做爲ES的默認方式使用的. 若是在這兩個版本中想使用單播, 須要設置discovery.zen.ping.multicast.enable爲false.

但自從ES 2.0以來, 單播是Zen discovery惟一可用的選擇.

首先, 你須要經過discovery.zen.ping.unicast.hosts參數指定一組用於發現和鏈接節點的hosts. 爲了簡單, 能夠爲集羣中的每一個節點設置相同的值. 咱們的集羣中使用了全部master節點的地址.

discovery.zen.minimum_master_nodes參數用於控制最小的合理master節點數, 使得集羣中其餘節點可被發現和操做. 一般, 在多於2個節點的集羣中建議該參數設置的值不小於2. 另一種計算方式是(master節點數/2 + 1).

Data節點和master節點以前有兩種檢測方式:

  • master向全部其餘節點發起ping請求, 以確認該節點是否存活

  • 其餘的節點向master節點發現ping請求,以確認master是否存活,並決定是否須要開始新一輪的選舉

節點檢測過程由discovery.zen.fd.ping_timeout參數設置, 默認值爲30s, 決定了一個發起ping請求的節點的響應等待時間. 若是你的集羣帶寬不足或網絡擁堵, 則須要合理的從新調整該參數. 若是網絡較差,該參數要相應的設置大一些, 值越大, 節點發現的失敗的風險也就越低.

Loggly的discovery.zen參數設置以下:

discovery.zen.df.ping_timeout: 30s
discovery.zen.mininum_master_nodes: 2
discovery.zen.ping.unicast.hosts: ["esmaster01", "esmaster02", "esmaster03"]

就是說30s內須要有節點檢測響應返回(經過discovery.zen.df.ping_timeout設置的).另外,其餘節點至少要檢測到2個master節點(咱們總共有3個master節點), 第三個參數是說咱們的單播主機分別爲esmaster01, esmaster02和esmaster03.

5: 提防"DELETE_all"

ES的DELETE API容許你經過一個請求(使用通配符或_all)刪除全部的索引數據, 意識到這一點很是重要.以下:

curl -XDELETE 'http://localhost:9200/*/'
curl -XDELETE 'http://localhost:9200/_all'

雖然這個功能很強大,卻也極爲危險,特別是在生產環境. 在咱們全部的集羣中, 咱們都經過action.destructive_requires_name:true參數禁用了該刪除功能.

這個參數由ES 1.0併入, 並替換掉了0.90版本中使用的action.disable_delete_all_indices參數.

6: 使用Doc Values

在ES2.0及以上版本中, Doc Values是默認使用的.而在較早的版本中則須要顯示指定.Doc Values經過少許額外的索引和磁盤開銷, 提供了比在normal字段上更高效的排序和聚合操做.本質上, Doc Values經過把ES轉變爲列式存儲, 進而使得ES大量的分詞特性比預想的更高效.

爲了深刻理解Doc Values帶來的好處, 下面將把Doc Values與normal字段進行對比.

當在normal字段上進行排序或聚合操做時, 將致使大量的fielddata cache.由於當字段第一次被緩存時, ES須要爲該字段每一個可能的取值分配大量的堆空間, 並從每一個文檔中獲取字段值數據. 由於這個過程可能須要從磁盤中讀取數據, 由於將會十分耗時.一旦數據緩存完成, 之後再對該字段值的使用都會使用先前緩存的數據, 因此速度也會更快.但當有過多的字段被載入到緩存中時, 就會觸發緩存淘汰機制, 一些字段將被汰出, 相應的再次使用被汰出的字段時, 就是又一次的耗時載入過程. 爲了高效, 你可能想減小或下降緩存汰出, 這意味着你要減小或限制將被緩存的字段數量.

與之不一樣, Doc Values使用基於磁盤的數據結構, 並映射到進程的內存空間, 從而減小對堆空間的佔用, 並具備與fielddata cache相匹敵的性能. 雖然在數據第一次從硬盤讀取並載入時依然會有起始開銷, 然而這一些都有操做系統的文件系統緩存進行處理, 因此只有你真正須要的數據纔會被讀入.

簡而言之, Doc Values減小了堆空間使用(相應的下降了GC影響), 並經過文件系統緩存減小讀取的數據, 從而提升了總體性能.

7: ES shard分配相關的參數設置

shard分配就是把shard分散到不一樣節點的過程,能夠發生在初始化備份階段, 副本分配階段或者節點再平衡過程當中.也就是說它發生在任何節點增長或移除的過程當中.

參數cluster.routing.allocation.cluster_concurrent_rebalance決定了在shard再平衡過程當中容許併發的shard數.合適的設置由你使用的硬件性能決定, 如集羣節點使用的CPU核數, IO性能等.若是參數設置的不合理,將會對ES索引過程的性能帶來必定的影響.

cluster.routing.allocation.cluster_concurrent_rebalance:2

ES默認設置的值爲2, 也就是說在任什麼時候候最多隻容許同時移動2個shards的數據.設置一個不過高的合理數值老是值得的,雖然shard再平衡的併發數受到制約, 但卻不會對索引數據形成影響.

另一個值得一提的參數是cluster.routing.allocation.disk.threshold_enabled.若是這個參數設置爲true, 則在shard分配過程當中爲shard預留空閒的磁盤空間, 相反若是設置爲false,則分配到該節點上的shard數據的將來增長將受到限制--沒有足夠的空間.

當threshold_enabled設置爲true, 有兩個相應的指標能夠配置:low 和 high.

  • low 定義了當磁盤使用量超過該指標後,ES將再也不爲該節點分配shard, 默認值爲85%

  • high 定義了當磁盤使用量超過該指標後,將有shard從該節點中移出, 默認值爲90%

這兩個參數便可按已使用量的百分比定義(例如,80%是說使用了80%的磁盤,尚有20%空閒), 也能夠按最小可用磁盤空間定義(例如,20GB是說該節點尚有20GB空閒空間).

若是你有大量的小shards, ES使用的默認值可能會有些保守. 例如你有1TB的存儲空間,而每一個shard的大小僅爲10GB, 理論上該節點能容納100個數據shards.若是採用上面的默認設置, 在ES認爲節點飽和前, 你最多隻能存儲80個shards.

因此爲了找出一個合理設置, 你須要仔細觀察在shard生命週期中的容量變化, 同時爲之預留必定的安全空間.在上面的例子中, 假若有5個數據shards, 則須要確認在任什麼時候候都要有50GB的可用空間(不是空閒空間, 是5個shards將佔用的總空間).對於1TB的設備, 若是不考慮安全空間, low的值可設置爲95%. 然而乘以50%的安全係數, 則須要至少預留75GB的空閒空間, 相應的合理的low值應爲92.5%.

8: 合理的恢復設置幫你提高節點重啓速度

ES提供了幾個屬性用於提升集羣恢復速度,縮短節點重啓時間.合理的取值依賴於你的硬件能力(硬盤和網絡速度一般會是瓶頸), 因此能給出的最好的建議就是嘗試,嘗試,再嘗試.

  • 控制單個節點併發恢復數據的shard數:

    cluster.routing.allocation.node_concurrent_recoveries

    shard數據恢復是一個IO密集型操做, 所以須要根據實際情形設置參數.在ES 5.x版本中, 這個參數分拆成兩個新的設置:

cluster.routing.allocation.node_concurrent_incoming_recoveries
cluster.routing.allocation.node_concurrent_outgoing_recoveries
  • 控制單個節點上初始的主shard併發數:

    cluster.routing.allocation.node_initial_primaries_recoveries
  • 控制一個shard恢復數據時並行打開的數據流個數:

    indices.recovery.concurrent_streams
  • 與數據流緊密相關的是可用的帶寬限制:

    indices.recovery.max_bytes_per_sec

    實際使用的硬件配置直接決定了以上幾個參數的最優值設置.使用SSD硬盤以及高速的(10G)以太網結構和使用機械硬盤以及1G的以太網結構將有巨大的差異.

只有在集羣重啓的時候,纔會使用以上數據恢復相關的參數設置.

9: 合理的線程池設置避免數據丟失

爲了提升節點內的線程管理, ES維護了多個線程池.

在Loggly, 咱們在使用_bulk操做來處理索引請求時發現, 設置合適的threadpool.bulk.queue_size對避免_bulk重試以及由其可能引發的數據丟失相當重要.

threadpool.bulk.queue_size: 5000

上面的參數用於設置bulk的隊列長度, 即當節點的每一個shard在處理bulk請求時, 若是無可用線程時, 能爲每一個shard排隊等待的請求數量.這個參數應該與你的bulk請求負載相匹配, 若是設置太小, 而bulk請求較多時, ES會返回一個RemoteTransportException.

如上所述, bulk請求涉及到的每一個shard的數據都在這個隊列裏, 所以合理的設置是bulk的併發數乘以這些請求相關的shard數. 好比說: 單個bulk請求包含的數據分佈在10個shards上, 即使只有一次bulk請求, 你也要有一個至少長度爲10的隊列設置.話說回來, 若是設置過大則會消耗更多的JVM堆空間(同時意味你正提交的數據量可能超出你實際能索引的能力), 然而卻能減化你的客戶端處理邏輯.

要麼設置一個相對合適的較大的隊列值, 要麼在你的代碼中合理的處理掉RemoteTransportException. 若是處理不當, 則會面臨數據丟失的風險. 下面的異常模仿的是隊列長度爲10,而併發發起了超過10個bulk請求的場景:

RemoteTransportException[[<Bantam>][inet[/192.168.76.1:9300]][bulk/shard]]; nested: EsRejectedExecutionException[rejected execution (queue capacity 10) on org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction$AsyncShardOperationAction$1@13fe9be];
相關文章
相關標籤/搜索