分布式搜尋引擎面試題系列(建議收藏)

2019-10-28     IT技術分享

1.說一下es的分布式架構原理 / es是如何實現分布式的

核心思想就是在多台機器上啟動多個 es 進程實例,組成了一個 es 集群。

創建一個index,index包含多個shard,每個shard都是一個最小工作單元,每個 shard 存儲部分數據。

一個shard 的數據實際是有多個備份,就是說每個 shard 都有一個 primary shard ,接受寫和讀請求,但是還有幾個 replica shard ,負責容錯,以及承擔讀請求負載。 primary shard 寫入數據之後,會將數據同步到其他幾個 replica shard 上去。這樣,每個 shard 的數據都有多個備份,如果某個機器宕機了,還有別的數據副本在別的機器上呢,這樣就實現了高可用。

es 集群多個節點,會自動選舉一個節點為 master 節點,這個 master 節點其實就是干一些管理的工作的,比如維護索引元數據、負責切換 primary shard 和 replica shard 身份等。要是 master 節點宕機了,那麼會重新選舉一個節點為 master 節點。

如果某個非 master 節點宕機了。那麼此節點上的 primary shard 就沒了。那好,master 會讓 primary shard 對應的 replica shard(在其他機器上)切換為 primary shard。如果宕機的機器修復了,修復後的節點上的shard也不再是 primary shard,而是 replica shard。同步後續修改的數據之類的,讓集群恢復正常。

上述就是 ElasticSearch 作為一個分布式搜尋引擎最基本的一個架構設計。

2.說一下es的寫入數據流程以及底層原理

1)客戶端選擇一個node (es節點)發送請求過去,這個node (es節點)就是coordinating node (協調節點),對document (文檔)進行路由,將請求轉發給對應的node 2)實際的node上的primary shard處理請求,然後將數據同步到replica node 3)coordinating node,如果發現primary node和所有replica node都搞定之後,就返迴響應結果給客戶端

es寫入數據的原理

  1. 先寫入buffer,在buffer里的時候數據是搜索不到的; 同時將數據寫入translog日誌文件
  2. 如果b uffer快滿了,或者每隔一秒鐘,就會將buffer數據refresh到一個新的segment file中並清空buffer,但是此時數據不是直接進入segment file的磁碟文件的,而是先進入os cache的。 當數據進入os cache後,就代表該數據可以被檢索到了。 因此說es是准實時的,這個過程就是 refresh
  3. 只要數據進入os cache,此時就可以讓這個segment file的數據對外提供搜索了
  4. 重複1~3步驟,新的數據不斷進入buffer和translog,不斷將buffer數據寫入一個又一個新的segment file中去,每次refresh完buffer清空,translog保留。 隨著這個過程推進,translog會變得越來越大。 當translog達到一定長度的時候,就會觸發commit操作。
  5. commit操作(也叫 flush 操作,默認每隔30分鐘執行一次):執行refresh操作 -> 寫commit point -> 將os cache數據fsync強刷到磁碟上去 -> 清空translog日誌文件
  6. commit操作保證了在機器宕機時,buffer和os cache中未同步到segment file中的數據還可以在重啟之後恢復到內存buffer和os cache中去,
  7. translog其實也是先寫入os cache的,默認每隔5秒刷一次到磁碟中去,所以默認情況下,可能有5秒的數據會僅僅停留在buffer或者translog文件的os cache中,如果此時機器掛了,會丟失5秒鐘的數據。 但是這樣性能比較好,最多丟5秒的數據。 也可以將translog設置成每次寫操作必須是直接fsync到磁碟,但是性能會差很多。
  8. 如果是刪除操作,commit的時候會生成一個.del文件,裡面將某個doc標識為deleted狀態,那麼搜索的時候根據.del文件就知道這個doc被刪除了
  9. 如果是更新操作,就是將原來的doc標識為deleted狀態,然後新寫入一條數據
  10. buffer每次refresh一次,就會產生一個segment file,所以默認情況下是1秒鐘一個segment file,segment file會越來越多,此時會定期執行merge,當segment多到一定的程度時,自動觸發merge操作
  11. 每次 merge 的時候,會將多個segment file合併成一個,同時這裡會將標識為deleted的doc給物理刪除掉,然後將新的segment file寫入磁碟,這裡會寫一個commit point,標識所有新的segment file,然後打開segment file供搜索使用,同時刪除舊的segment file。

3.說一下es的讀數據流程

讀數據分為GET和Search,即查詢一條 和 搜索操作。

查詢:

查詢操作,即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給客戶端

搜索:

  • 客戶端發送請求到一個 coordinate node
  • 協調節點將搜索請求轉發到所有的shard對應的 primary shard 或 replica shard
  • query phase 每個shard將自己的搜索結果(本質上就是一些doc id),返回給 coordinate node ,由 coordinate node 進行數據的合併、排序、分頁等,以生成最終結果
  • fetch phase 接著由 coordinate node ,根據doc id去各節點中拉取實際的 document 數據,最終返回給客戶端

4.為什麼es集群至少需要三個節點

首先需要知道一點:es的配置文件中有一個配置:discovery.zen.minimum master nodes:2 ,默認是2,即選舉Master時需要的節點數。

假設es有兩個節點,master node 和 data node,即選舉Master時鎖需要的節點為 1,此時出現網絡波動,導致 master node 和 data node出現短暫的斷開連接,根據選舉規則,data node將自己選舉為master,當網絡波動結束後,就會出現兩個master,即我們所說的腦裂。

當es有三個節點,master node、data data(A)、data node(B),即選舉Master時鎖需要的節點為 2,此時出現網絡波動,master node 和 A 、B斷開連接,則 master node降級,A、B進行選舉,假設選舉為A為master,當網絡恢復後,之前的 master node --> data node,之前的 data node(A)--> master node。

所以,通過配置 minimum master nodes 來防止出現腦裂,在生產過程中, 為了儘量保持集群高可用, 至少需要三台機器搭建集群。

end:如果你覺得本文對你有幫助的話,記得關注點贊轉發,你的支持就是我更新動力。

文章來源: https://twgreatdaily.com/zh-my/SRLdE24BMH2_cNUg_1In.html