天天看點

突破Java面試(15)-分布式搜尋引擎Elastic Search的工作流程1 面試題2 考點分析3 詳解參考

以下用ES表Elastic Search

1 面試題

ES寫入/查詢資料的工作原理是什麼呀?

2 考點分析

面試官就是想看看你是否了解ES的一些基本原理.

ES無非就是寫/查資料,你如果不明白你發起寫入/搜尋請求後,ES做了什麼,那你該勸退了.

3 詳解

3.1 ES寫資料的執行流程

  • 用戶端選擇一個node發送請求過去,該node就是coordinating node(協調節點);
  • coordinating node對document進行路由,将請求轉發給對應的node(有primary shard);
  • 實際的node上的primary shard處理請求,然後将資料同步到replica node;
  • coordinating node若發現primary node和所有replica node都響應完操作後,就傳回結果給用戶端.

3.2 ES讀資料的執行流程

查詢,GET某一條資料,寫入了某個document,該document會自動給你配置設定一個全局唯一id-doc id,同時也是根據doc id進行hash路由到對應的primary shard上面去.也可以手動指定doc id,比如用訂單id,使用者id.

可以通過doc id來查詢,會根據doc id進行hash,判斷出當時把doc id配置設定到了哪個shard,從那個shard去查詢

  • 用戶端發送請求到任意一個node,成為coordinate node
  • coordinate node對document路由,将請求轉發到對應的node,此時會使用round-robin随機輪詢算法,在primary shard及其所有replica中随機選擇,使讀請求負載均衡
  • 接收請求的node傳回document給coordinate node
  • coordinate node傳回document給用戶端

3.3 ES查詢資料的執行流程

最強大的是做全文檢索,比如有三條資料

JavaEdge公衆号呀
Java學習者們建議關注哦
java就很好學了呢           
注意這裡的字母大小寫喲~

根據

Java

關鍵詞來搜尋,将包含Java的document給搜尋出來

ES就會給你傳回:JavaEdge公衆号呀,Java學習者們建議關注哦

  • 用戶端發送請求到一個

    coordinate node

  • 協調節點将搜尋請求轉發到所有的shard對應的

    primary shard

    replica shard

  • query phase

    每個shard将自己的搜尋結果(本質上就是一些doc id),傳回給

    coordinate node

    ,由

    coordinate node

    進行資料的合并、排序、分頁等,以生成最終結果
  • fetch phase

    接着由

    coordinate node

    ,根據doc id去各節點中拉取實際的

    document

    資料,最終傳回給用戶端

3.4 搜尋的底層原理 - 反向索引

畫圖說明傳統資料庫和反向索引的差別

(待更新...)

3.5 ES 寫資料的執行流程

  • ES讀寫底層原理示意圖
    突破Java面試(15)-分布式搜尋引擎Elastic Search的工作流程1 面試題2 考點分析3 詳解參考

(1) 先寫入buffer,在buffer裡的時候資料是搜尋不到的;同時将資料寫入translog日志檔案

(2) 如果buffer将滿,或者定時,就會将buffer中的資料refresh到一個新的segment file中

但此時資料不是直接進入segment file磁盤檔案的,而是先進入os cache,即refresh.

每1s,ES 将buffer中的資料寫到一個新的segment file,segment file磁盤檔案每 s 生成一個,其隻存儲最近1s内buffer中寫入的資料

  • 如果buffer中此時無資料,自然不會執行refresh操作
  • 如果buffer中有資料,預設每1s執行一次refresh,刷入一個新的segment file中

在作業系統的磁盤檔案中都有os cache(作業系統緩存),即資料寫入磁盤檔案前,會先進入os cache,即進入OS級别的一個記憶體緩存

隻要buffer中的資料被refresh刷入os cache,該資料就可被搜尋到

為什麼稱 ES 是準實時(NRT,near real-time)的?

預設每1 s refresh一次,是以 ES 是準實時的,寫入的資料1s之後才能被觀測到.

可以通過ES的RESRful API或者Java API,手動執行一次refresh,即手動将buffer中資料刷入os cache,讓資料立馬就可被搜尋到.隻要資料被輸入os cache中,buffer就會被清空,因為不需要保留緩存了,資料在translog裡面已經持久化到磁盤.

(3) 隻要資料進入os cache,此時就可以讓這個segment file的資料對外提供搜尋服務了.

(4) 重複1~3步驟,新資料不斷進入buffer和translog,不斷将buffer資料寫入一個個segment file,每次refresh完,清空buffer,保留translog.

随着該過程不斷推進,translog會變臃腫,當translog達到一定大小時,就會觸發commit操作.

buffer中的資料,倒是好,每隔1秒就被刷到os cache中去,然後這個buffer就被清空了。是以說這個buffer的資料始終是可以保持住不會填滿es程序的記憶體的。

每次一條資料寫入buffer,同時會寫入一條日志到translog日志檔案中去,是以這個translog日志檔案是不斷變大的,當translog日志檔案大到一定程度的時候,就會執行commit操作。

(5) commit操作第一步,就是将buffer中現有資料refresh到os cache,清空buffer

(6)将一個commit point寫到磁盤,以辨別該commit point對應的所有segment file

(7)強行将os cache中所有資料都

fsync

到磁盤

translog日志檔案的作用是什麼?

就是在你執行commit之前,資料要麼是停留在buffer中,要麼os cache中

無論是buffer還是os cache都是記憶體,一旦這台機器宕掉,資料就會全丢

是以需要将資料對應的操作寫入一個專門的日志檔案,translog日志檔案中,一旦此時機器當機,再次重新開機的時候,ES會自動讀取translog日志檔案中的資料,恢複到記憶體buffer和os cache中去。

commit操作

  • 寫commit point
  • 将os cache資料fsync強刷到磁盤上去
  • 清空translog日志檔案

(8) 将現有的translog清空,接着重新開機啟用一個translog,此時commit操作完成。預設每隔30分鐘會自動執行一次commit,但是如果translog過大,也會觸發commit。整個commit的過程,叫做flush操作。我們可以手動執行flush操作,就是将所有os cache資料刷到磁盤檔案中去。

不叫做commit操作,flush操作。es中的flush操作,就對應着commit的全過程。我們也可以通過es api,手動執行flush操作,手動将os cache中的資料fsync強刷到磁盤上去,記錄一個commit point,清空translog日志檔案。

9)translog其實也是先寫入os cache,預設每5s刷到磁盤

是以預設情況下,可能有5秒的資料僅僅駐存在buffer或者translog檔案的os cache中,若此時機器當機,會丢失5s的資料.

但是這樣性能比較好,最多丢5s的資料.也可将translog設定成每次寫操作必須是直接fsync到磁盤,但是性能會差很多.

實際上在這裡,若面試官沒有問你ES丢資料的問題,就可在這裡給面試官炫一把:

其實ES第一是準實時性的,資料寫入1s後可以搜尋到;

可能會丢失資料,你的資料有5s會停留在buffer/translog os cache/segment file os cache中,有5s的資料不在磁盤上,此時如果當機,會導緻這5s的資料丢失.

如果你希望一定不能丢失資料的話,你可以設定個參數,官方文檔,百度一下.

每次寫入一條資料,都是寫入buffer,同時寫入磁盤上的translog,但是這會導緻寫性能、寫入吞吐量會下降一個數量級.

本來一秒鐘可以寫2000條,現在你一秒鐘隻能寫200條,都有可能.

小結

資料先寫入記憶體 buffer,然後每隔 1s,将資料 refresh 到 os cache,到了 os cache 資料就能被搜尋到(是以我們才說 es 從寫入到能被搜尋到,中間有 1s 的延遲).

每隔 5s,将資料寫入 translog 檔案(這樣如果機器當機,記憶體資料全沒,最多會有 5s 的資料丢失),translog 大到一定程度,或者預設每隔 30mins,會觸發 commit 操作,将緩沖區的資料都 flush 到 segment file 磁盤檔案中.

資料寫入 segment file 之後,同時就建立好了反向索引。

3.6 ES 删除資料的執行流程

(1) commit時會生成一個

.del

檔案,将某個doc辨別為

deleted

态,那麼搜尋的時候根據

.del

檔案就知道該doc已被删除

3.7 ES 更新資料的執行流程

(1) 将原來的doc辨別為

deleted

狀态,然後新寫入一條資料

(2) buffer每refresh一次,就會産生一個segment file,是以預設情況下是1s一個segment file,segment file會越來越多,此時會定期執行merge

(3) 每次merge時,會将多個segment file合并成一個,同時這裡會将辨別為

deleted

的doc給實體删除掉,然後将新的segment file寫入磁盤,這裡會寫一個commit point,辨別所有新的segment file,然後打開segment file供搜尋使用,同時删除舊的segment file.

ES 裡的寫流程,有4個底層的核心概念,refresh、flush、translog、merge

當segment file多到一定程度的時候,es就會自動觸發merge操作,将多個segment file給merge成一個segment file。

參考

《Java工程師面試突擊第1季-中華石杉老師》

Github

繼續閱讀