引文
Elasticsearch基于Lucene所以很多系統實現都在其中,所以可以先看看Lucene的實現:
https://blog.csdn.net/qq_35040959/article/details/147931034
項目組件
不像Kafka這種頂級項目核心性能組件全自己實現,ELK中有很多引用至第三方開放庫;
網絡模型-Netty
網絡模型多重要不必多說,Elasticsearch基于Netty,一個認可度&社區活躍度都非常高的NIO多路復用模型;
存儲模型-Lucene
Elasticsearch基于Lucene上提供分布式服務;具體可以看看這篇文章對存儲模型的介紹
https://blog.csdn.net/qq_35040959/article/details/147931034
分布式查詢
//GET http://localhost:9200/my-index-000001/_search
{"from": 10, //第二頁"size": 10, //查詢十條"_source": ["title", "priority"], //指定字段返回"query": {"bool": {"must": [{ "match": { "title": "guide" } }//全匹配]}}
}
構建查詢
org.elasticsearch.action.search.TransportSearchAction#executeSearch
分發到每個shard
org.elasticsearch.action.search.AbstractSearchAsyncAction#run
發送shard請求
org.elasticsearch.transport.TransportService#sendLocalRequest
單條查詢(查詢Lucene)
org.elasticsearch.search.query.QueryPhase#searchWithCollector
[Query]階段查詢結果,只包含指定范圍的score與docid
org.elasticsearch.action.search.QueryPhaseResultConsumer#consumeResult
聚合數據(對多個shard的數據聚合排序后決定實際獲取的)
org.elasticsearch.action.search.FetchSearchPhase#innerRun -> resultConsumer.reduce();
[Fetch]階段,讀取指定docid文檔
org.elasticsearch.action.search.FetchSearchPhase#executeFetch
[Query]&[Fetch]步驟基于Lucene的相關性查詢與指定docid查詢
深分頁-search_after分頁查詢
**<<分布式查詢>>**是基于相關性的查詢,這種查詢會掃描倒排表構建K-TOP堆,這種方法在深頁后(如10000頁后)查詢成本非常高;
search_after必須指定"sort"排序字段后通過"search_after"定位在排序中的其實位置,這種方式沒有構建K-TOP的流程,定位到指定的排序偏移量后直接獲取,更加快速;
缺點就是不再是相關性排序;
//GET http://localhost:9200/my-index-000001/_search
{"from": 0, "size": 10, "_source": ["title", "priority"], "query": {"bool": {"must": [{ "match": { "title": "guide" } }]}},"sort": [{ "_id": "asc" } //強制要求:指定排序(不難理解:沒有固定的排序規則,那么給定的search_after將沒法用于排查此前已經吐出的數據)],"search_after": [ "QHHnZ5cBTxKf9WaM2zpf"] //強制要求:上一頁最后一條文檔_id
}
基于DocValues實現
深分頁-scroll查詢
search_after不是基于快照,會受到同步數據插入影響,scroll查詢對索引打快照;
資源占用與性能對比:
特性 | Scroll API | Search After API |
---|---|---|
上下文維護 | 需要維護 _scroll_id 上下文 | 無上下文,僅需傳遞排序值 |
內存占用 | 高(需緩存快照和游標狀態) | 低(無持久化狀態) |
CPU 開銷 | 低(順序掃描,無需動態排序) | 中等(需動態定位排序值位置) |
網絡傳輸 | 批量高效(適合大數據量導出) | 單頁高效(適合高頻分頁請求) |
實時性與一致性對比
特性 | Scroll API | Search After API |
---|---|---|
數據一致性 | 強一致性(基于快照,數據靜態) | 弱一致性(實時數據,可能變化) |
反映更新 | 否(快照期間索引更新不可見) | 是(每次查詢讀取最新數據) |
適用場景 | 全量導出、離線分析(如日志備份) | 實時分頁、深度檢索(如用戶搜索) |
todo 快照原理
一致性協議
分布式問題
主節點
Elastic有一下節點角色[Master Node(主節點)]、[Data Node(數據節點)]、[Coordinating Node(協調節點)]三個核心角色(還有其他的角色),主要介紹主節點:
??主節點(Master Node)??
-
??職責??:管理集群元數據(索引創建/刪除、分片分配、節點狀態監控)。
-
細分類型??:
– 候選主節點(Master-Eligible)??:參與選舉,可成為主節點(配置:node.roles: [master])。
– 僅投票主節點(Voting-Only)??:僅參與選舉投票,不擔任主節點(配置:node.roles: [master, voting_only])。 -
??最佳實踐??:
– 生產集群需至少 ??3個候選主節點??,且半數以上非僅投票節點,避免腦裂。
– 與數據節點分離,確保穩定性。
集群中將會只有一個節點成為[Master Node]并為集群中需要強一致性的行為做唯一決策出口;
主節點選舉
Elasticsearch 的選舉機制是對 Raft (論文)的??工程化改良??,通過犧牲部分理論嚴謹性換取分布式搜索場景下的實操效率,核心差異本質是??性能與強一致性之間的權衡??
1. 多票制??
??節點在同一任期內可多次投票,支持多個候選人同時當選。
??沖突解決??:若多個候選人同時當選,ES 采用 ??“最后當選者有效”?? 原則(如 Node2 先當選,但收到 Node3 的投票請求后主動退位,最終 Node3 成為主節點)。
??目的??:避免小規模集群中因節點同時競選導致選舉失敗(如 3 節點均自投),提升選舉速度。
2. 預投票流程(PreVote)的差異??
??Raft :
候選人需確認日志足夠新(term 更大或 index 更大)且獲得多數支持,才發起正式投票。
??Elasticsearch 的 PreVote??:
檢查條件更寬松:僅需候選人 term ≥ 當前節點 term,或 term 相同時候選人版本號 ≥ 當前節點版本號。
??風險??:寬松條件可能導致網絡分區節點頻繁發起無效選舉,但提高選舉速度,同時 ES 通過動態退避機制(back_off_time)降低影響。
3. 狀態轉換規則的靈活性??
??Raft 的嚴格轉換??:
節點狀態需按 Follower → Candidate → Leader 順序轉換,且 Leader 退位后需先回退至 Follower。
??Elasticsearch 的靈活轉換??:
??Leader 退位規則??:Leader 收到任何更高 term 的投票請求(RequestVote)時,??立即退位為 Candidate??(而非 Follower)。
??目的??:加速新主節點產生,避免舊 Leader 阻塞選舉進程。
4. 腦裂處理策略??
??Raft 的嚴格多數票??:
僅獲得多數票的分區可選出 Leader,天然避免腦裂。
??Elasticsearch 的妥協方案??:
允許多個分區同時選出 Leader,但通過 ??“最后當選者有效”?? 和 ??Leader 主動退位?? 解決沖突(非實時避免腦裂)。
??風險??:極端情況下可能短暫存在多主,但數據一致性通過分片分配機制(主節點唯一管理元數據)保障。
5. 性能與規模適應性??
??選舉速度??:
ES 的并行投票和寬松 PreVote 使??小規模集群選舉更快??(通常 < 500ms)。
Raft 的嚴格流程在大規模集群中??穩定性更優??,ES 需依賴參數調優(如增大 cluster.election.duration)減少競爭。
??大規模集群挑戰??:
ES 在超 40 節點時可能出現??頻繁主節點切換??,Raft 可穩定支持 50+ 節點。
cluster.election.initial_timeout: 100ms # 初始等待時間
cluster.election.back_off_time: 100ms # 退避增量
cluster.election.max_timeout: 10s # 最大等待時間
僅投票節點(Voting-only Node)??:專用于投票但不存儲數據,提升大規模集群選舉穩定性。
??小規模集群??(<10 節點):ES 默認配置即可,利用多票制提升選舉效率。
??大規模集群??(>20 節點):
部署專用??主節點??(無 data 角色)和??僅投票節點??;
調大 cluster.election.duration(如 1s)減少競爭。
添加新分片&重平衡的影響
一、修改副本分片數(Replicas)??
??場景??:增加或減少副本分片數(如從number_of_replicas=1改為2)。
??特點??:在線操作,無需重建索引,數據不會丟失。
添加副本可以在線操作:看過raft論文的添加新節點的流程就能理解為什么可以在線操作;
二、修改主分片數(Primary Shards)??
??場景??:調整主分片數量(如從number_of_shards=3改為6)。
??特點??:必須重建索引!原始索引數據不會自動遷移到新分片布局。
ES數據使用計算Hash分配數據,修改只能重建索引;