從物理空間概念,Elasticsearch 分布式系統會有 3 個關鍵點需要學習。本次總結了下面相關內容:
- 分布式
- 節點 & 集群
- 主分片及副本
一、Elasticsearch 分布式
Elasticsearch 分布式特性包括如下幾個點:
1.1 高可用
什么是高可用?CAP 定理是分布式系統的基礎,也是分布式系統的 3 個指標:
- Consistency(一致性)
- Availability(可用性)
- Partition tolerance(分區容錯性)
那高可用(High Availability)是什么?高可用,簡稱 HA,是系統一種特征或者指標,通常是指,提供一定性能上的服務運行時間,高於平均正常時間段。反之,消除系統服務不可用的時間。
衡量系統是否滿足高可用,就是當一台或者多台服務器宕機的時候,系統整體和服務依然正常可用。舉個例子,一些知名的網站保證 4 個 9 以上的可用性,也就是可用性超過 99.99%。那 0.01% 就是所謂故障時間的百分比。
Elasticsearch 在高可用性上,體現如下兩點:
- 服務可用性:允許部分節點停止服務,整體服務沒有影響
- 數據可用性:允許部分節點丟失,最終不會丟失數據
1.2 可擴展
隨着公司業務發展,Elasticsearch 也面臨兩個挑戰:
- 搜索數據量從百萬到億量級
- 搜索請求 QPS 也猛增
那么需要將原來節點和增量數據重新從 10 個節點分布到 100 個節點。Elasticsearch 可以橫向擴展至數百(甚至數千)的服務器節點,同時可以處理PB級數據。Elasticsearch 為了可擴展性而生,由小規模集群增長為大規模集群的過程幾乎完全自動化,這是水平擴展的體現。
1.3 Elasticsearch 分布式特性
上面通過可擴展性,可以看出 Elasticsearch 分布式的好處明顯:
- 存儲可以水平擴容,水平空間換時間
- 部分節點停止服務,整個集群服務不受影響,照樣正常提供服務
Elasticsearch 在后台自動完成了分布式相關工作,如下:
- 自動分配文檔到不同分片或者多節點上
- 均衡分配分片到集群節點上,index 和 search 操作時進行負載均衡
- 復制每個分片,支持數據冗余,防止硬件故障數據丟失
- 集群擴容時,無縫整合新節點,並且重新分配分片
- 等等
Elasticsearch 集群知識點如下:
- 不同集群通過名字區分,默認集群名稱為 “elasticsearch”
- 集群名 cluster name ,可以通過配置文件修改或者命令行 -E cluster.name=user-es-cluster 進行設置
- 一個集群由多個節點組成
二、Elasticsearch 節點 & 集群

Elasticsearch 集群有多個節點組成,形成分布式集群。那么,什么是節點呢?
節點(Node),就是一個 Elasticsearch 應用實例。大家都知道 Elasticsearch 源代碼是 Java 寫的,那么節點就是一個 Java 進程。所以類似 Spring 應用一樣,一台服務器或者本機可以運行多個節點,只要對應的端口不同即可。但生產服務器中,一般一台服務器運行一個 Elasticsearch 節點。還有需要注意:
- Elasticsearch 都會有 name ,通過 -E node.name=node01 指定或者配置文件中配置
- 每個節點啟動成功,都會分配對應得一個 UID ,保存在 data 目錄
可以通過命令 _cluster/health 查看集群的健康狀態,如下:
- Green 主分片與副本分片都正常
- Yellow 主分片正常,副本分片不正常
- Red 有主分片不正常,可能某個分片容量超過了磁盤大小等

如圖,有主(Master)節點和其他節點。那么節點有多少類型呢?
2.1 Master-eligible Node 和 Master Node
Elasticsearch 被啟動后,默認就是 Master-eligible Node。然后通過參與選主過程,可以成為 Master Node。具體選主原理,后續單獨寫一篇文章。Master Node 有什么作用呢?
- Master Node 負責同步集群狀態信息:
- 所有節點信息
- 所有索引即其 Mapping 和 Setting 信息
- 所有分片路由信息
- 主節點負責集群相關的操作,例如創建或刪除索引,跟蹤哪些節點是集群的一部分,以及決定將哪些分片分配給哪些節點。
- 只能 Master 節點可以修改信息,是因為這樣就能保證數據得一致性
2.2 Data Node 和 Coordinating Node
Data Node,又稱數據節點。用於保存數據,其在數據擴展上起至關重要的作用。
Coordinating Node,是負責接收任何 Client 的請求,包括 REST Client 等。該節點將請求分發到合適的節點,最終把結果匯集到一起。一般來說,每個節點默認起到了 Coordinating Node 的職責。
2.3 其他節點類型
還有其他節點類型,雖然不常見,但需要知道:
- Hot & Warm Node:不同硬件配置的 Data Node,用來實現冷熱數據節點架構,降低運維部署的成本
- Machine Learning Node:負責機器學習的節點
- Tribe Node:負責連接不同的集群。支持跨集群搜索 Cross Cluster Search
一般在開發環境中,設置單一的角色節點:
- master node:通過 node.master 配置,默認 true
- data node:通過 node.data 配置,默認 true
- ingest node:通過 node.ingest 配置,默認 true
-
ingest 節點可以看作是數據前置處理轉換的節點,支持 pipeline管道 設置,可以使用 ingest 對數據進行過濾、轉換等操作,類似於 logstash 中 filter 的作用,功能相當強大。
我把Ingest節點的功能抽象為:大數據處理環節的“ETL”——抽取、轉換、加載
-
- coordinating node:默認每個節點都是 coordinating 節點,設置其他類型全部為 false。
-
搜索請求在兩個階段中執行(query 和 fetch),這兩個階段由接收客戶端請求的節點 - 協調節點協調。
在請求階段,協調節點將請求轉發到保存數據的數據節點。 每個數據節點在本地執行請求並將其結果返回給協調節點。
在收集fetch階段,協調節點將每個數據節點的結果匯集為單個全局結果集。
-
- machine learning:通過 node.ml 配置,默認 true,需要通過 x-pack 開啟。
三、主分片及副本

同樣看這個圖,3 個節點分別為 Node1、Node2、Node3。並且 Node3 上面有一個主分片 P0 和一個副本 R2。那什么是主分片呢?
主分片,用來解決數據水平擴展的問題。比如上圖這個解決可以將數據分布到所有節點上:
- 節點上可以有主分片,也可以沒有主分片
- 主分片在索引創建的時候確定,后續不允許修改。除非 Reindex 操作進行修改
副本,用來備份數據,提高數據的高可用性。副本分片是主分片的拷貝
- 副本分片數,可以動態調整
- 增加副本數,可以一定程度上提高服務讀取的吞吐和可用性
如何查看 Elasticsearch 集群的分片配置呢?可以從 settings 從看出:
- number_of_shards 主分片數
- number_of_replicas 副本分片數
{
"my_index": {
"settings": {
"index": {
"number_of_shards": "8",
"number_of_replicas": "1"
}
}
}
}
實戰建議:對生產環境中,分片設置很重要,需要最好容量評估與規划
- 根據數據容量評估分配數,設置過小,后續無法水平擴展;單分片數據量太大,也容易導致數據分片耗時嚴重
- 分片數設置如果太大,會導致資源浪費,性能降低;同時也會影響搜索結果打分和搜索准確性
索引評估,每個索引下面的單分片數不用太大。如何評估呢?比如這個索引 100 G 數據量,那設置 10 個分片,平均每個分片數據量就是 10G 。每個分片 10 G 數據量這么大,耗時肯定嚴重。所以根據評估的數據量合理安排分片數即可。如果需要調整主分片數,那么需要進行 reindex 等遷索引操作。
小結
從上一篇到這一篇:
- 一個節點,對應一個實例
- 一個節點,可以多個索引
- 一個索引,可以多個分片
- 一個分片,對應底層一個 lucene 分片
比如知道了搜索性能場景,例如多少數據量,多大的寫入,是寫為主還是查詢為主等等,才可以確定:
- 磁盤,推薦 SSD,JVM最大 Xmx 不要超過30G。副本分片至少設置為1。主分片,單個存儲不要超過 30 GB,按照這個你推算出分片數,進行設定。
- 集群中磁盤快滿的時候,你再增加機器,確實可能導致新建的索引全部分配到新節點上去的可能性。最終導致數據分配不均。所以要記得監控集群,到70%就需要考慮刪除數據或是增加節點
- 可以設置最大分片數緩解這個問題。
- 分片的尺寸如果過大,確實也沒有快速恢復的辦法,所以盡量保證分片的size在40G以下

Cooridnating Node是原來的Client node的,主要功能是來分發請求和合並結果的。新版本已經取消了Client node這種節點角色,在所有節點默認就是Coordinating node,且不能關閉該屬性。
如果把node.master, node.data, node.ingest都設為false, 那個這個節點就純粹是作為Coordinating node, 這種節點需要有足夠多的內存和CPU來處理 合並數據集合。
Ingest node主要是通過使用ingest pipeline來對文檔在索引之前進行轉換或者增強。
Tribe node也是一類特殊的Coordinating node (Client node),這種節點可以連接多個集群,可以對多個集群進行搜索和其他操作。
Ingest 節點能解決什么問題?
上面的Ingest節點介紹太官方,看不大懂怎么辦?來個實戰場景例子吧。
思考問題1:線上寫入數據改字段需求
如何在數據寫入階段修改字段名(不是修改字段值)?
思考問題2:線上業務數據添加特定字段需求
如何在批量寫入數據的時候,每條document插入實時時間戳?
這時,腦海里開始對已有的知識點進行搜索。
針對思考問題1:字段值的修改無非:update,update_by_query?但是字段名呢?貌似沒有相關接口或實現。
針對思考問題2:插入的時候,業務層面處理,讀取當前時間並寫入貌似可以,有沒有不動業務層面的字段的方法呢?
答案是有的,這就是Ingest節點的妙處。
Ingest節點基本概念
在實際文檔索引發生之前,使用Ingest節點預處理文檔。Ingest節點攔截批量和索引請求,它應用轉換,然后將文檔傳遞回索引或Bulk API。
強調一下: Ingest節點處理時機——在數據被索引之前,通過預定義好的處理管道對數據進行預處理。
默認情況下,所有節點都啟用Ingest,因此任何節點都可以處理Ingest任務。我們也可以創建專用的Ingest節點。
要禁用節點的Ingest功能,需要在elasticsearch.yml 設置如:node.ingest:false
這里就涉及幾個知識點:
- 1、預處理 pre-process
要在數據索引化(indexing)之前預處理文檔。 - 2、管道 pipeline
每個預處理過程可以指定包含一個或多個處理器的管道。
管道的實際組成:
{ "description" : "...", "processors" : [ ... ] }
description:管道功能描述。
processors:注意是數組,可以指定1個或多個處理器。
處理器 processors
每個處理器以某種特定方式轉換文檔。
例如,管道可能有一個從文檔中刪除字段的處理器,然后是另一個重命名字段的處理器。
這樣,再反過來看第4部分就很好理解了。
Ingest API
Ingest API共分為4種操作,分別對應:
PUT(新增)、
GET(獲取)、
DELETE(刪除)、
Simulate (仿真模擬)。
模擬管道AP Simulate 針對請求正文中提供的文檔集執行特定管道。
除此之外,高階操作包括:
1、支持復雜條件的Nested類型的操作;
2、限定條件的管道操作;
3、限定條件的正則操作等。
詳細內容,參見官網即可。
常見的處理器有如下28種,舉例:
append處理器:添加1個或1組字段值;
convert處理器:支持類型轉換。
Ingest節點和Logstash Filter 啥區別?
業務選型中,肯定會問到這個問題。


區別一:支持的數據源不同。
Logstash:大量的輸入和輸出插件(比如:kafka,redis等)可供使用,還可用來支持一系列不同的架構。
Ingest節點:不能從外部來源(例如消息隊列或數據庫)提取數據,必須批量bulk或索引index請求將數據推送到 Elasticsearch.
區別二:應對數據激增的能力不同。
Logstash:Logstash 可在本地對數據進行緩沖以應對采集驟升情況。如前所述,Logstash 同時還支持與大量不同的消息隊列類型進行集成。
Ingest節點:極限情況下會出現:在長時間無法聯系上 Elasticsearch 或者 Elasticsearch 無法接受數據的情況下,均有可能會丟失數據。
區別三:處理能力不同。
Logstash:支持的插件和功能點較Ingest節點多很多。
Ingest節點:支持28類處理器操作。Ingest節點管道只能在單一事件的上下文中運行。Ingest通常不能調用其他系統或者從磁盤中讀取數據。
區別四:排他式功能支持不同。
Ingest節點:支持采集附件處理器插件,此插件可用來處理和索引常見格式(例如 PPT、XLS 和 PDF)的附件。
Logstash:不支持如上文件附件類型。
master節點
主要功能是維護元數據,管理集群各個節點的狀態,數據的導入和查詢都不會走master節點,所以master節點的壓力相對較小,因此master節點的內存分配也可以相對少些;但是master節點是最重要的,如果master節點掛了或者發生腦裂了,你的元數據就會發生混亂,那樣你集群里的全部數據可能會發生丟失,所以一定要保證master節點的穩定性。
data node
是負責數據的查詢和導入的,它的壓力會比較大,它需要分配多點的內存,選擇服務器的時候最好選擇配置較高的機器(大內存,雙路CPU,SSD... 土豪~);data node要是壞了,可能會丟失一小份數據。
client node
是作為任務分發用的,它里面也會存元數據,但是它不會對元數據做任何修改。client node存在的好處是可以分擔下data node的一部分壓力;為什么client node能分擔data node的一部分壓力?因為es的查詢是兩層匯聚的結果,第一層是在data node上做查詢結果匯聚,然后把結果發給client node,client node接收到data node發來的結果后再做第二次的匯聚,然后把最終的查詢結果返回給用戶;所以我們看到,client node幫忙把第二層的匯聚工作處理了,自然分擔了data node的壓力。
這里,我們可以舉個例子,當你有個大數據查詢的任務(比如上億條查詢任務量)丟給了es集群,要是沒有client node,那么壓力直接全丟給了data node,如果data node機器配置不足以接受這么大的查詢,那么就很有可能掛掉,一旦掛掉,data node就要重新recover,重新reblance,這是一個異常恢復的過程,這個過程的結果就是導致es集群服務停止... 但是如果你有client node,任務會先丟給client node,client node要是處理不來,頂多就是client node停止了,不會影響到data node,es集群也不會走異常恢復。
對於es 集群為何要設計這三種角色的節點,也是從分層邏輯去考慮的,只有把相關功能和角色划分清楚了,每種node各盡其責,才能發揮出分布式集群的效果
一般地,ElasticSearch集群中每個節點都有成為主節點的資格,也都存儲數據,還可以提供查詢服務。這些功能是由兩個屬性控制的(node.master和node.data)。默認情況下這兩個屬性的值都是true。
在生產環境下,如果不修改ElasticSearch節點的角色信息,在高數據量,高並發的場景下集群容易出現腦裂等問題,下面詳細介紹一下這兩個屬性的含義以及不同組合可以達到的效果。
一、node.master
這個屬性表示節點是否具有成為主節點的資格。
注意:此屬性的值為true,並不意味着這個節點就是主節點。因為真正的主節點,是由多個具有主節點資格的節點進行選舉產生的。所以,這個屬性只是代表這個節點是不是具有主節點選舉資格。
二、node.data
這個屬性表示節點是否存儲數據。
三、四種組合配置方式
(1)node.master: true node.data: true
這種組合表示這個節點即有成為主節點的資格,又存儲數據。
如果某個節點被選舉成為了真正的主節點,那么他還要存儲數據,這樣對於這個節點的壓力就比較大了。ElasticSearch默認每個節點都是這樣的配置,在測試環境下這樣做沒問題。實際工作中建議不要這樣設置,因為這樣相當於主節點和數據節點的角色混合到一塊了。
(2)node.master: false node.data: true
這種組合表示這個節點沒有成為主節點的資格,也就不參與選舉,只會存儲數據。
這個節點我們稱為data(數據)節點。在集群中需要單獨設置幾個這樣的節點負責存儲數據,后期提供存儲和查詢服務。
(3)node.master: true node.data: false
這種組合表示這個節點不會存儲數據,有成為主節點的資格,可以參與選舉,有可能成為真正的主節點,這個節點我們稱為master節點。
(4)node.master: false node.data: false
這種組合表示這個節點即不會成為主節點,也不會存儲數據,這個節點的意義是作為一個client(客戶端)節點,主要是針對海量請求的時候可以進行負載均衡
ElasticSearch啟動時,會占用兩個端口9200和9300
9200作為Http協議,主要用於外部通訊
9300作為Tcp協議,jar之間就是通過tcp協議通訊
ES集群之間是通過9300進行通訊
