記憶體吞金獸(Elasticsearch)的那些事兒 -- 寫入&檢索原理
阿新 • • 發佈:2021-08-25
寫入原理
協調節點
客戶端寫入一條資料,到Elasticsearch叢集裡邊就是由協調節點來處理這次請求:
叢集上的每個節點都是coordinating node
,表明這個節點可以做路由。比如節點1接收到了請求,但發現這個請求的資料應該是由節點2處理(因為主分片在節點2上),所以會把請求轉發到節點2上。
- coodinate node通過hash演算法可以計算出是在哪個主分片上,然後路由到對應的index node
shard = hash(document_id) % (num_of_primary_shards)
節點寫入
- 將資料寫到記憶體快取區
- 然後將資料寫到translog快取區
- 定期將資料從buffer中refresh到FileSystemCache中,生成segment檔案,一旦生成segment檔案,就能通過索引查詢到了
- refresh完,memory buffer就清空了。
- 定期將translog 從buffer flush到磁碟中
- 定期/定量從FileSystemCache中,結合translog內容
flush index
到磁碟中。
預設配置執行流程:
- Elasticsearch會把資料先寫入記憶體緩衝區,然後每隔1s重新整理到檔案系統快取區(當資料被重新整理到檔案系統緩衝區以後,資料才可以被檢索到)。所以:Elasticsearch寫入的資料需要1s才能查詢到
- 為了防止節點宕機,記憶體中的資料丟失,Elasticsearch會另寫一份資料到日誌檔案上,但最開始的還是寫到記憶體緩衝區,每隔5s才會將緩衝區的刷到磁碟中。所以:Elasticsearch某個節點如果掛了,可能會造成有5s的資料丟失。
- 等到磁碟上的translog檔案大到一定程度或者超過了30分鐘,會觸發commit操作,將記憶體中的segment檔案非同步刷到磁碟中,完成持久化操作。
說白了就是:寫記憶體緩衝區(定時去生成segment,生成translog),能夠讓資料能被索引、被持久化。最後通過commit完成一次的持久化。
最後
等主分片寫完了以後,會將資料並行傳送到副本集節點上,等到所有的節點寫入成功就返回ack
更新和刪除
- 給對應的
doc
記錄打上.del
標識,如果是刪除操作就打上delete
狀態,如果是更新操作就把原來的doc
標誌為delete
,然後重新新寫入一條資料 -
前面提到了,每隔1s會生成一個segment 檔案,那segment檔案會越來越多越來越多。Elasticsearch會有一個merge任務,會將多個segment檔案合併成一個segment檔案。在合併的過程中,會把帶有
delete
狀態的doc
給物理刪除掉。
檢索原理
核心
link:3. 資料結構
兩大類
es的檢索主要分為兩大類
- 根據ID查詢doc(實時)
- 檢索記憶體的Translog檔案
- 檢索硬碟的Translog檔案
- 檢索硬碟的Segment檔案
- 根據query(搜尋詞)去查詢匹配的doc(近實時,因為segment檔案是每隔一秒才生成一次的)
- 查詢Segment
三階段
-
QUERY_AND_FETCH(查詢完就返回整個Doc內容)
-
QUERY_THEN_FETCH(先查詢出對應的Doc id ,然後再根據Doc id 匹配去對應的文件)
-
DFS_QUERY_THEN_FETCH(先算分,再查詢)
- 「這裡的分指的是詞頻率和文件的頻率(Term Frequency、Document Frequency)眾所周知,出現頻率越高,相關性就更強」
QUERY_THEN_FETCH總體的大概流程流程:
- 客戶端請求傳送到叢集的某個節點上。叢集上的每個節點都是coordinate node(協調節點)
- 然後協調節點將搜尋的請求轉發到所有分片上(主分片和副本分片都行)
- 每個分片將自己搜尋出的結果
(doc id)
返回給協調節點,由協調節點進行資料的合併、排序、分頁等操作,產出最終結果。 - 接著由協調節點根據
doc id
去各個節點上拉取實際的document
資料,最終返回給客戶端。
Query Phase階段時節點做的事:
- 協調節點向目標分片傳送查詢的命令(轉發請求到主分片或者副本分片上)
- 資料節點(在每個分片內做過濾、排序等等操作),返回
doc id
給協調節點
Fetch Phase階段時節點做的是:
- 協調節點得到資料節點返回的
doc id
,對這些doc id
做聚合,然後將目標資料分片傳送抓取命令(希望拿到整個Doc記錄) - 資料節點按協調節點發送的
doc id
,拉取實際需要的資料返回給協調節點