硬件配置優化
升級硬件設備配置一直都是提高服務能力最快速有效的手段,在系統層面能夠影響應用性能的一般包括三個因素:CPU、內存和 IO,可以從這三方面進行 ES 的性能優化工作。
CPU 配置
一般說來,CPU 繁忙的原因有以下幾個:
- 線程中有無限空循環、無阻塞、正則匹配或者單純的計算;
- 發生了頻繁的 GC;
- 多線程的上下文切換;
大多數 Elasticsearch 部署往往對 CPU 要求不高。因此,相對其它資源,具體配置多少個(CPU)不是那么關鍵。你應該選擇具有多個內核的現代處理器,常見的集群使用 2 到 8 個核的機器。如果你要在更快的 CPUs 和更多的核數之間選擇,選擇更多的核數更好。多個內核提供的額外并發遠勝過稍微快一點點的時鐘頻率。
內存配置
如果有一種資源是最先被耗盡的,它可能是內存。排序和聚合都很耗內存,所以有足夠的堆空間來應付它們是很重要的。即使堆空間是比較小的時候,也能為操作系統文件緩存提供額外的內存。因為 Lucene 使用的許多數據結構是基于磁盤的格式,Elasticsearch 利用操作系統緩存能產生很大效果。
64 GB 內存的機器是非常理想的,但是 32 GB 和 16 GB 機器也是很常見的。少于8 GB 會適得其反(你最終需要很多很多的小機器),大于 64 GB 的機器也會有問題。
由于 ES 構建基于 lucene,而 lucene 設計強大之處在于 lucene 能夠很好的利用操作系統內存來緩存索引數據,以提供快速的查詢性能。lucene 的索引文件 segements 是存儲在單文件中的,并且不可變,對于 OS 來說,能夠很友好地將索引文件保持在 cache 中,以便快速訪問;因此,我們很有必要將一半的物理內存留給 lucene;另一半的物理內存留給 ES(JVM heap)。
內存分配
當機器內存小于 64G 時,遵循通用的原則,50% 給 ES,50% 留給 lucene。
當機器內存大于 64G 時,遵循以下原則:
- 如果主要的使用場景是全文檢索,那么建議給 ES Heap 分配 4~32G 的內存即可;其它內存留給操作系統,供 lucene 使用(segments cache),以提供更快的查詢性能。
- 如果主要的使用場景是聚合或排序,并且大多數是 numerics,dates,geo_points 以及 not_analyzed 的字符類型,建議分配給 ES Heap 分配 4~32G 的內存即可,其它內存留給操作系統,供 lucene 使用,提供快速的基于文檔的聚類、排序性能。
- 如果使用場景是聚合或排序,并且都是基于 analyzed 字符數據,這時需要更多的 heap size,建議機器上運行多 ES 實例,每個實例保持不超過 50% 的 ES heap 設置(但不超過 32 G,堆內存設置 32 G 以下時,JVM 使用對象指標壓縮技巧節省空間),50% 以上留給 lucene。
禁止 swap
禁止 swap,一旦允許內存與磁盤的交換,會引起致命的性能問題。可以通過在 elasticsearch.yml 中 bootstrap.memory_lock: true,以保持 JVM 鎖定內存,保證 ES 的性能。
GC 設置
老的版本中官方文檔 中推薦默認設置為:Concurrent-Mark and Sweep(CMS),給的理由是當時G1 還有很多 BUG。
原因是:已知JDK 8附帶的HotSpot JVM的早期版本存在一些問題,當啟用G1GC收集器時,這些問題可能導致索引損壞。受影響的版本早于JDK 8u40隨附的HotSpot版本。來源于官方說明
實際上如果你使用的JDK8較高版本,或者JDK9+,我推薦你使用G1 GC;因為我們目前的項目使用的就是G1 GC,運行效果良好,對Heap大對象優化尤為明顯。修改jvm.options文件,將下面幾行:
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
更改為
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50
其中 -XX:MaxGCPauseMillis是控制預期的最高GC時長,默認值為200ms,如果線上業務特性對于GC停頓非常敏感,可以適當設置低一些。但是 這個值如果設置過小,可能會帶來比較高的cpu消耗。
G1對于集群正常運作的情況下減輕G1停頓對服務時延的影響還是很有效的,但是如果是你描述的GC導致集群卡死,那么很有可能換G1也無法根本上解決問題。通常都是集群的數據模型或者Query需要優化。
磁盤
硬盤對所有的集群都很重要,對大量寫入的集群更是加倍重要(例如那些存儲日志數據的)。硬盤是服務器上最慢的子系統,這意味著那些寫入量很大的集群很容易讓硬盤飽和,使得它成為集群的瓶頸。
在經濟壓力能承受的范圍下,盡量使用固態硬盤(SSD)。固態硬盤相比于任何旋轉介質(機械硬盤,磁帶等),無論隨機寫還是順序寫,都會對 IO 有較大的提升。
- 如果你正在使用 SSDs,確保你的系統 I/O 調度程序是配置正確的。當你向硬盤寫數據,I/O 調度程序決定何時把數據實際發送到硬盤。大多數默認 *nix 發行版下的調度程序都叫做 cfq(完全公平隊列)。
- 調度程序分配時間片到每個進程。并且優化這些到硬盤的眾多隊列的傳遞。但它是為旋轉介質優化的:機械硬盤的固有特性意味著它寫入數據到基于物理布局的硬盤會更高效。
- 這對 SSD 來說是低效的,盡管這里沒有涉及到機械硬盤。但是,deadline 或者 noop 應該被使用。deadline 調度程序基于寫入等待時間進行優化,noop 只是一個簡單的 FIFO 隊列。
這個簡單的更改可以帶來顯著的影響。僅僅是使用正確的調度程序,我們看到了 500 倍的寫入能力提升。
如果你使用旋轉介質(如機械硬盤),嘗試獲取盡可能快的硬盤(高性能服務器硬盤,15k RPM 驅動器)。
使用 RAID0 是提高硬盤速度的有效途徑,對機械硬盤和 SSD 來說都是如此。沒有必要使用鏡像或其它 RAID 變體,因為 Elasticsearch 在自身層面通過副本,已經提供了備份的功能,所以不需要利用磁盤的備份功能,同時如果使用磁盤備份功能的話,對寫入速度有較大的影響。
最后,避免使用網絡附加存儲(NAS)。人們常聲稱他們的 NAS 解決方案比本地驅動器更快更可靠。除卻這些聲稱,我們從沒看到 NAS 能配得上它的大肆宣傳。NAS 常常很慢,顯露出更大的延時和更寬的平均延時方差,而且它是單點故障的。
索引優化設置
索引優化主要是在 Elasticsearch 的插入層面優化,Elasticsearch 本身索引速度其實還是蠻快的,具體數據,我們可以參考官方的 benchmark 數據。我們可以根據不同的需求,針對索引優化。
批量提交
當有大量數據提交的時候,建議采用批量提交(Bulk 操作);此外使用 bulk 請求時,每個請求不超過幾十M,因為太大會導致內存使用過大。
比如在做 ELK 過程中,Logstash indexer 提交數據到 Elasticsearch 中,batch size 就可以作為一個優化功能點。但是優化 size 大小需要根據文檔大小和服務器性能而定。
像 Logstash 中提交文檔大小超過 20MB,Logstash 會將一個批量請求切分為多個批量請求。
如果在提交過程中,遇到 EsRejectedExecutionException 異常的話,則說明集群的索引性能已經達到極限了。這種情況,要么提高服務器集群的資源,要么根據業務規則,減少數據收集速度,比如只收集 Warn、Error 級別以上的日志。
增加 Refresh 時間間隔
為了提高索引性能,Elasticsearch 在寫入數據的時候,采用延遲寫入的策略,即數據先寫到內存中,當超過默認1秒(index.refresh_interval)會進行一次寫入操作,就是將內存中 segment 數據刷新到磁盤中,此時我們才能將數據搜索出來,所以這就是為什么 Elasticsearch 提供的是近實時搜索功能,而不是實時搜索功能。
如果我們的系統對數據延遲要求不高的話,我們可以通過延長 refresh 時間間隔,可以有效地減少 segment 合并壓力,提高索引速度。比如在做全鏈路跟蹤的過程中,我們就將 index.refresh_interval 設置為30s,減少 refresh 次數。再如,在進行全量索引時,可以將 refresh 次數臨時關閉,即 index.refresh_interval 設置為-1,數據導入成功后再打開到正常模式,比如30s。
在加載大量數據時候可以暫時不用 refresh 和 repliccas,index.refresh_interval 設置為-1,index.number_of_replicas 設置為0。
相關原理,請參考[原理:ES原理之索引文檔流程詳解]
修改 index_buffer_size 的設置
索引緩沖的設置可以控制多少內存分配給索引進程。這是一個全局配置,會應用于一個節點上所有不同的分片上。
indices.memory.index_buffer_size: 10%
indices.memory.min_index_buffer_size: 48mb
indices.memory.index_buffer_size 接受一個百分比或者一個表示字節大小的值。默認是10%,意味著分配給節點的總內存的10%用來做索引緩沖的大小。這個數值被分到不同的分片(shards)上。如果設置的是百分比,還可以設置 min_index_buffer_size (默認 48mb)和 max_index_buffer_size(默認沒有上限)。
修改 translog 相關的設置
一是控制數據從內存到硬盤的操作頻率,以減少硬盤 IO。可將 sync_interval 的時間設置大一些。默認為5s。
index.translog.sync_interval: 5s
也可以控制 tranlog 數據塊的大小,達到 threshold 大小時,才會 flush 到 lucene 索引文件。默認為512m。
index.translog.flush_threshold_size: 512mb
translog我們在[原理:ES原理之索引文檔流程詳解]也有介紹。
注意 _id 字段的使用
_id 字段的使用,應盡可能避免自定義 _id,以避免針對 ID 的版本管理;建議使用 ES 的默認 ID 生成策略或使用數字類型 ID 做為主鍵。
注意 _all 字段及 _source 字段的使用
_all 字段及 _source 字段的使用,應該注意場景和需要,_all 字段包含了所有的索引字段,方便做全文檢索,如果無此需求,可以禁用;_source 存儲了原始的 document 內容,如果沒有獲取原始文檔數據的需求,可通過設置 includes、excludes 屬性來定義放入 _source 的字段。
合理的配置使用 index 屬性
合理的配置使用 index 屬性,analyzed 和 not_analyzed,根據業務需求來控制字段是否分詞或不分詞。只有 groupby 需求的字段,配置時就設置成 not_analyzed,以提高查詢或聚類的效率。
減少副本數量
Elasticsearch 默認副本數量為3個,雖然這樣會提高集群的可用性,增加搜索的并發數,但是同時也會影響寫入索引的效率。
在索引過程中,需要把更新的文檔發到副本節點上,等副本節點生效后在進行返回結束。使用 Elasticsearch 做業務搜索的時候,建議副本數目還是設置為3個,但是像內部 ELK 日志系統、分布式跟蹤系統中,完全可以將副本數目設置為1個。
查詢方面優化
Elasticsearch 作為業務搜索的近實時查詢時,查詢效率的優化顯得尤為重要。
路由優化
當我們查詢文檔的時候,Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?它其實是通過下面這個公式來計算出來的。
shard = hash(routing) % number_of_primary_shards
routing 默認值是文檔的 id,也可以采用自定義值,比如用戶 ID。
不帶 routing 查詢
在查詢的時候因為不知道要查詢的數據具體在哪個分片上,所以整個過程分為2個步驟:
- 分發:請求到達協調節點后,協調節點將查詢請求分發到每個分片上。
- 聚合:協調節點搜集到每個分片上查詢結果,再將查詢的結果進行排序,之后給用戶返回結果。
帶 routing 查詢
查詢的時候,可以直接根據 routing 信息定位到某個分配查詢,不需要查詢所有的分配,經過協調節點排序。
向上面自定義的用戶查詢,如果 routing 設置為 userid 的話,就可以直接查詢出數據來,效率提升很多。
Filter VS Query
盡可能使用過濾器上下文(Filter)替代查詢上下文(Query)
- Query:此文檔與此查詢子句的匹配程度如何?
- Filter:此文檔和查詢子句匹配嗎?
Elasticsearch 針對 Filter 查詢只需要回答「是」或者「否」,不需要像 Query 查詢一樣計算相關性分數,同時Filter結果可以緩存。
深度翻頁
在使用 Elasticsearch 過程中,應盡量避免大翻頁的出現。
正常翻頁查詢都是從 from 開始 size 條數據,這樣就需要在每個分片中查詢打分排名在前面的 from+size 條數據。協同節點收集每個分配的前 from+size 條數據。協同節點一共會受到 N*(from+size) 條數據,然后進行排序,再將其中 from 到 from+size 條數據返回出去。如果 from 或者 size 很大的話,導致參加排序的數量會同步擴大很多,最終會導致 CPU 資源消耗增大。
可以通過使用 Elasticsearch scroll 和 scroll-scan 高效滾動的方式來解決這樣的問題。
也可以結合實際業務特點,文檔 id 大小如果和文檔創建時間是一致有序的,可以以文檔 id 作為分頁的偏移量,并將其作為分頁查詢的一個條件。
腳本(script)合理使用
我們知道腳本使用主要有 3 種形式,內聯動態編譯方式、_script 索引庫中存儲和文件腳本存儲的形式;一般腳本的使用場景是粗排,盡量用第二種方式先將腳本存儲在 _script 索引庫中,起到提前編譯,然后通過引用腳本 id,并結合 params 參數使用,即可以達到模型(邏輯)和數據進行了分離,同時又便于腳本模塊的擴展與維護。
Cache的設置及使用
- QueryCache: ES查詢的時候,使用filter查詢會使用query cache, 如果業務場景中的過濾查詢比較多,建議將querycache設置大一些,以提高查詢速度。
indices.queries.cache.size:10%(默認),可設置成百分比,也可設置成具體值,如256mb。
當然也可以禁用查詢緩存(默認是開啟), 通過index.queries.cache.enabled:false設置。
- FieldDataCache: 在聚類或排序時,field data cache會使用頻繁,因此,設置字段數據緩存的大小,在聚類或排序場景較多的情形下很有必要,可通過indices.fielddata.cache.size:30% 或具體值10GB來設置。但是如果場景或數據變更比較頻繁,設置cache并不是好的做法,因為緩存加載的開銷也是特別大的。
- ShardRequestCache: 查詢請求發起后,每個分片會將結果返回給協調節點(Coordinating Node), 由協調節點將結果整合。如果有需求,可以設置開啟; 通過設置index.requests.cache.enable: true來開啟。不過,shard request cache只緩存hits.total, aggregations, suggestions類型的數據,并不會緩存hits的內容。也可以通過設置indices.requests.cache.size: 1%(默認)來控制緩存空間大小。
更多查詢優化經驗
- query_string 或 multi_match的查詢字段越多, 查詢越慢。可以在mApping階段,利用copy_to屬性將多字段的值索引到一個新字段,multi_match時,用新的字段查詢。
- 日期字段的查詢, 尤其是用now 的查詢實際上是不存在緩存的,因此, 可以從業務的角度來考慮是否一定要用now, 畢竟利用query cache 是能夠大大提高查詢效率的。
- 查詢結果集的大小不能隨意設置成大得離譜的值, 如query.setSize不能設置成 Integer.MAX_VALUE, 因為ES內部需要建立一個數據結構來放指定大小的結果集數據。
- 避免層級過深的聚合查詢, 層級過深的aggregation , 會導致內存、CPU消耗,建議在服務層通過程序來組裝業務,也可以通過pipeline的方式來優化。
- 復用預索引數據方式來提高AGG性能:
如通過 terms aggregations 替代 range aggregations, 如要根據年齡來分組,分組目標是: 少年(14歲以下) 青年(14-28) 中年(29-50) 老年(51以上), 可以在索引的時候設置一個age_group字段,預先將數據進行分類。從而不用按age來做range aggregations, 通過age_group字段就可以了。
通過開啟慢查詢配置定位慢查詢
不論是數據庫還是搜索引擎,對于問題的排查,開啟慢查詢日志是十分必要的,ES 開啟慢查詢的方式有多種,但是最常用的是調用模板 API 進行全局設置:
PUT /_template/{TEMPLATE_NAME}
{
"template":"{INDEX_PATTERN}",
"settings" : {
"index.indexing.slowlog.level": "INFO",
"index.indexing.slowlog.threshold.index.warn": "10s",
"index.indexing.slowlog.threshold.index.info": "5s",
"index.indexing.slowlog.threshold.index.debug": "2s",
"index.indexing.slowlog.threshold.index.trace": "500ms",
"index.indexing.slowlog.source": "1000",
"index.search.slowlog.level": "INFO",
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.query.trace": "500ms",
"index.search.slowlog.threshold.fetch.warn": "1s",
"index.search.slowlog.threshold.fetch.info": "800ms",
"index.search.slowlog.threshold.fetch.debug": "500ms",
"index.search.slowlog.threshold.fetch.trace": "200ms"
},
"version" : 1
}
PUT {INDEX_PAATERN}/_settings
{
"index.indexing.slowlog.level": "INFO",
"index.indexing.slowlog.threshold.index.warn": "10s",
"index.indexing.slowlog.threshold.index.info": "5s",
"index.indexing.slowlog.threshold.index.debug": "2s",
"index.indexing.slowlog.threshold.index.trace": "500ms",
"index.indexing.slowlog.source": "1000",
"index.search.slowlog.level": "INFO",
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.query.trace": "500ms",
"index.search.slowlog.threshold.fetch.warn": "1s",
"index.search.slowlog.threshold.fetch.info": "800ms",
"index.search.slowlog.threshold.fetch.debug": "500ms",
"index.search.slowlog.threshold.fetch.trace": "200ms"
}
這樣,在日志目錄下的慢查詢日志就會有輸出記錄必要的信息了。
{CLUSTER_NAME}_index_indexing_slowlog.log
{CLUSTER_NAME}_index_search_slowlog.log
數據結構優化
基于 Elasticsearch 的使用場景,文檔數據結構盡量和使用場景進行結合,去掉沒用及不合理的數據。
盡量減少不需要的字段
如果 Elasticsearch 用于業務搜索服務,一些不需要用于搜索的字段最好不存到 ES 中,這樣即節省空間,同時在相同的數據量下,也能提高搜索性能。
避免使用動態值作字段,動態遞增的 mapping,會導致集群崩潰;同樣,也需要控制字段的數量,業務中不使用的字段,就不要索引。控制索引的字段數量、mapping 深度、索引字段的類型,對于 ES 的性能優化是重中之重。
以下是 ES 關于字段數、mapping 深度的一些默認設置:
index.mapping.nested_objects.limit: 10000
index.mapping.total_fields.limit: 1000
index.mapping.depth.limit: 20
Nested Object vs Parent/Child
盡量避免使用 nested 或 parent/child 的字段,能不用就不用;nested query 慢,parent/child query 更慢,比 nested query 慢上百倍;因此能在 mapping 設計階段搞定的(大寬表設計或采用比較 smart 的數據結構),就不要用父子關系的 mapping。
如果一定要使用 nested fields,保證 nested fields 字段不能過多,目前 ES 默認限制是 50。因為針對 1 個 document,每一個 nested field,都會生成一個獨立的 document,這將使 doc 數量劇增,影響查詢效率,尤其是 JOIN 的效率。
index.mapping.nested_fields.limit: 50
對比 |
Nested Object |
Parent/Child |
優點 |
文檔存儲在一起,因此讀取性高 |
父子文檔可以獨立更新,互不影響 |
缺點 |
更新父文檔或子文檔時需要更新整個文檔 |
為了維護 join 關系,需要占用部分內存,讀取性能較差 |
場景 |
子文檔偶爾更新,查詢頻繁 |
子文檔更新頻繁 |
選擇靜態映射,非必需時,禁止動態映射
盡量避免使用動態映射,這樣有可能會導致集群崩潰,此外,動態映射有可能會帶來不可控制的數據類型,進而有可能導致在查詢端出現相關異常,影響業務。
此外,Elasticsearch 作為搜索引擎時,主要承載 query 的匹配和排序的功能,那數據的存儲類型基于這兩種功能的用途分為兩類,一是需要匹配的字段,用來建立倒排索引對 query 匹配用,另一類字段是用做粗排用到的特征字段,如 ctr、點擊數、評論數等等。
document 模型設計
對于 MySQL,我們經常有一些復雜的關聯查詢。在 es 里該怎么玩兒,es 里面的復雜的關聯查詢盡量別用,一旦用了性能一般都不太好。
最好是先在 JAVA 系統里就完成關聯,將關聯好的數據直接寫入 es 中。搜索的時候,就不需要利用 es 的搜索語法來完成 join 之類的關聯搜索了。
document 模型設計是非常重要的,很多操作,不要在搜索的時候才想去執行各種復雜的亂七八糟的操作。es 能支持的操作就那么多,不要考慮用 es 做一些它不好操作的事情。如果真的有那種操作,盡量在 document 模型設計的時候,寫入的時候就完成。另外對于一些太復雜的操作,比如 join/nested/parent-child 搜索都要盡量避免,性能都很差的。
集群架構設計
合理的部署 Elasticsearch 有助于提高服務的整體可用性。
主節點、數據節點和協調節點分離
Elasticsearch 集群在架構拓樸時,采用主節點、數據節點和負載均衡節點分離的架構,在 5.x 版本以后,又可將數據節點再細分為“Hot-Warm”的架構模式。
Elasticsearch 的配置文件中有 2 個參數,node.master 和 node.data。這兩個參數搭配使用時,能夠幫助提供服務器性能。
主(master)節點
配置 node.master:true 和 node.data:false,該 node 服務器只作為一個主節點,但不存儲任何索引數據。我們推薦每個集群運行3 個專用的 master 節點來提供最好的彈性。使用時,你還需要將 discovery.zen.minimum_master_nodes setting 參數設置為 2,以免出現腦裂(split-brain)的情況。用 3 個專用的 master 節點,專門負責處理集群的管理以及加強狀態的整體穩定性。因為這 3 個 master 節點不包含數據也不會實際參與搜索以及索引操作,在 JVM 上它們不用做相同的事,例如繁重的索引或者耗時,資源耗費很大的搜索。因此不太可能會因為垃圾回收而導致停頓。因此,master 節點的 CPU,內存以及磁盤配置可以比 data 節點少很多的。
數據(data)節點
配置 node.master:false 和 node.data:true,該 node 服務器只作為一個數據節點,只用于存儲索引數據,使該 node 服務器功能單一,只用于數據存儲和數據查詢,降低其資源消耗率。
在 Elasticsearch 5.x 版本之后,data 節點又可再細分為“Hot-Warm”架構,即分為熱節點(hot node)和暖節點(warm node)。
hot 節點:
hot 節點主要是索引節點(寫節點),同時會保存近期的一些頻繁被查詢的索引。由于進行索引非常耗費 CPU 和 IO,即屬于 IO 和 CPU 密集型操作,建議使用 SSD 的磁盤類型,保持良好的寫性能;我們推薦部署最小化的 3 個 hot 節點來保證高可用性。根據近期需要收集以及查詢的數據量,可以增加服務器數量來獲得想要的性能。
將節點設置為 hot 類型需要 elasticsearch.yml 如下配置:
node.attr.box_type: hot
如果是針對指定的 index 操作,可以通過 settings 設置 index.routing.allocation.require.box_type: hot 將索引寫入 hot 節點。
warm 節點:
這種類型的節點是為了處理大量的,而且不經常訪問的只讀索引而設計的。由于這些索引是只讀的,warm 節點傾向于掛載大量磁盤(普通磁盤)來替代 SSD。內存、CPU 的配置跟 hot 節點保持一致即可;節點數量一般也是大于等于 3 個。
將節點設置為 warm 類型需要 elasticsearch.yml 如下配置:
node.attr.box_type: warm
同時,也可以在 elasticsearch.yml 中設置 index.codec:best_compression 保證 warm 節點的壓縮配置。
當索引不再被頻繁查詢時,可通過 index.routing.allocation.require.box_type:warm,將索引標記為 warm,從而保證索引不寫入 hot 節點,以便將 SSD 磁盤資源用在刀刃上。一旦設置這個屬性,ES 會自動將索引合并到 warm 節點。
協調(coordinating)節點
協調節點用于做分布式里的協調,將各分片或節點返回的數據整合后返回。該節點不會被選作主節點,也不會存儲任何索引數據。該服務器主要用于查詢負載均衡。在查詢的時候,通常會涉及到從多個 node 服務器上查詢數據,并將請求分發到多個指定的 node 服務器,并對各個 node 服務器返回的結果進行一個匯總處理,最終返回給客戶端。在 ES 集群中,所有的節點都有可能是協調節點,但是,可以通過設置 node.master、node.data、node.ingest 都為 false 來設置專門的協調節點。需要較好的 CPU 和較高的內存。
- node.master:false和node.data:true,該node服務器只作為一個數據節點,只用于存儲索引數據,使該node服務器功能單一,只用于數據存儲和數據查詢,降低其資源消耗率。
- node.master:true和node.data:false,該node服務器只作為一個主節點,但不存儲任何索引數據,該node服務器將使用自身空閑的資源,來協調各種創建索引請求或者查詢請求,并將這些請求合理分發到相關的node服務器上。
- node.master:false和node.data:false,該node服務器即不會被選作主節點,也不會存儲任何索引數據。該服務器主要用于查詢負載均衡。在查詢的時候,通常會涉及到從多個node服務器上查詢數據,并將請求分發到多個指定的node服務器,并對各個node服務器返回的結果進行一個匯總處理,最終返回給客戶端。
關閉 data 節點服務器中的 http 功能
針對 Elasticsearch 集群中的所有數據節點,不用開啟 http 服務。將其中的配置參數這樣設置,http.enabled:false,同時也不要安裝 head, bigdesk, marvel 等監控插件,這樣保證 data 節點服務器只需處理創建/更新/刪除/查詢索引數據等操作。
http 功能可以在非數據節點服務器上開啟,上述相關的監控插件也安裝到這些服務器上,用于監控 Elasticsearch 集群狀態等數據信息。這樣做一來出于數據安全考慮,二來出于服務性能考慮。
一臺服務器上最好只部署一個 node
一臺物理服務器上可以啟動多個 node 服務器節點(通過設置不同的啟動 port),但一臺服務器上的 CPU、內存、硬盤等資源畢竟有限,從服務器性能考慮,不建議一臺服務器上啟動多個 node 節點。
集群分片設置
ES 一旦創建好索引后,就無法調整分片的設置,而在 ES 中,一個分片實際上對應一個 lucene 索引,而 lucene 索引的讀寫會占用很多的系統資源,因此,分片數不能設置過大;所以,在創建索引時,合理配置分片數是非常重要的。一般來說,我們遵循一些原則:
控制每個分片占用的硬盤容量不超過 ES 的最大 JVM 的堆空間設置(一般設置不超過 32 G,參考上面的 JVM 內存設置原則),因此,如果索引的總容量在 500 G 左右,那分片大小在 16 個左右即可;當然,最好同時考慮原則 2。考慮一下 node 數量,一般一個節點有時候就是一臺物理機,如果分片數過多,大大超過了節點數,很可能會導致一個節點上存在多個分片,一旦該節點故障,即使保持了 1 個以上的副本,同樣有可能會導致數據丟失,集群無法恢復。所以,一般都設置分片數不超過節點數的 3 倍。