ES分佈式架構和底層原理分析

一  ES 簡介

     elasticsearch設計的理念就是分佈式搜索引擎,底層實現還是基於Lucene的,核心思想是在多臺機器上啓動多個es進程實例,組成一個es集羣。

二  es 概念

A 接近實時


es是一個接近實時的搜索平臺,這就意味着,從索引一個文檔直到文檔能夠被搜索到有一個輕微的延遲。

B 集羣(cluster)


一個集羣有多個節點(服務器)組成,通過所有的節點一起保存全部數據,通過聯合索引和搜索功能節點的集合,每一個集羣有一個唯一的名稱標識。

C 節點(node)


一個節點就是一個單一的服務器,是集羣的一部分,存儲數據,並且參與集羣和搜索功能,一個節點可以通過配置特定的名稱來加入特定的集羣,在一個集羣中,想啓動多少個節點就可以啓動多少個節點。

D 索引(index)


一個索引就是還有某些共有特性的文檔的集合,一個索引被一個名稱唯一標識,並且這個名稱被用於索引通過文檔去執行搜索,更新和刪除操作。

E 類型(type)


type 在6.0.0已經不贊成使用。

F 文檔(document)


一個文檔是一個基本的搜索單元。

三 小節


    es中,存儲數據的基本單位就是索引,比如說es中存儲了一些訂單系統的銷售數據,就應該在es中創建一個索引,order—index,所有的銷售數據就會都寫到這個索引裏面去,一個索引就像數據庫。而type就相當於每一張表,
一個index裏面可以有多個type,而mapping就相當於表的結構定義,定義了什麼字段類型等,你往index的一個type裏添加一行數據就叫做一個document,每一個document有多個field,每一個field就代表這個document的一個字段的值。

1 分片(shards)

      在一個搜索裏存儲的數據,潛在的情況下可能會超過單個節點的硬件的存儲限制,爲了解決這個問題,elasticsearch便提供了分片的功能,它可以將索引劃分爲多個分片,當你創建一個索引的時候,你就可以簡單的定義你想要的分片的數量,每一個分片本身是一個全功能的完全獨立的索引,可以部署到集羣中的任何一個節點。分片的兩個重要原因:
(1)它允許水平切分內容卷。
(2)它允許通過分片來分佈和執行操作來應對日益增長的執行量。

複製(replica)
      在一種網絡情況下,故障可能會隨時發生,有一個故障恢復機制是必須的,爲了達到這個目的,ES允許製作一個或多個拷貝放入一個叫做複製分片或短暫的複製品中。複製對於以下兩個主要原因很重要。
(1)高可用。它提供了高可用以來防止分片或者節點宕機,爲此,一個非常重要的注意點就是絕對不要將一個分片的拷貝放在跟這個分片相同的機器上。
(2)高併發。它允許你的分片可以提供超出自身吞吐量的搜索服務,搜索行爲可以在分片所有的拷貝中並行執行。


  總之,一個完整的流程就是,ES客戶端將一份數據寫入primary shard,它會將其分成成對的shard分片,並將數據進行復制,ES客戶端取數據的時候就會在replica或primary 的shard中去讀。ES集羣有多個節點,會自動選舉一個節點爲master節點,這個master節點其實就是幹一些管理類的操作,比如維護元數據,負責切換primary shard 和replica shard的身份之類的,要是master節點宕機了,那麼就會重新選舉下一個節點爲master節點。如果是非master宕機了,那麼就會有master節點,讓那個宕機的節點上的primary shard的身份轉移到replica shard上,如果修復了宕機的那臺機器,重啓之後,master節點就會控制將缺失的replica shard 分配過去,同步後續的修改工作,讓集羣恢復正常。

四 es寫入數據的過程

A 客戶端選擇一個node發送請求過去,這個node就是coordinating node (協調節點)。

B coordinating node,對document進行路由,將請求轉發給對應的node。

C 實際上的node上的primary shard處理請求,然後將數據同步到replica node。

D coordinating node,如果發現primary node和所有的replica node都搞定之後,就會返回請求到客戶端。

五 es讀數據過程

查詢,GET某一條的數據,寫入某個document,這個document會自動給你分配一個全局的唯一ID,同時根據這個ID進行hash路由到對應的primary shard上面去,當然也可以手動的設置ID

A 客戶端發送任何一個請求到任意一個node,成爲coordinate node。

B coordinate node 對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪訓算法,在primary shard 以及所有的replica中隨機選擇一個,讓讀請求負載均衡。

C 接受請求的node,返回document給coordinate note。

D coordinate node返回給客戶端。

六  es搜索數據過程

A 客戶端發送一個請求給coordinate node。

B 協調節點將搜索的請求轉發給所有的shard對應的primary shard 或replica shard。

C query phase:每一個shard 將自己搜索的結果(其實也就是一些唯一標識),返回給協調節點,有協調節點進行數據的合併,排序,分頁等操作,產出最後的結果。

D fetch phase ,接着由協調節點,根據唯一標識去各個節點進行拉去數據,最總返回給客戶端。

七 寫入數據的底層原理

A 數據先寫入到buffer裏面,在buffer裏面的數據是搜索不到的,同時將數據寫入到translog日誌文件之中。

B 如果buffer快滿了,或是一段時間之後,就會將buffer數據refresh到一個新的OS cache之中,然後每隔1秒,就會將OS cache的數據寫入到segment file之中,但是如果每一秒鐘沒有新的數據到buffer之中,就會創建一個新的空的segment file,只要buffer中的數據被refresh到OS cache之中,就代表這個數據可以被搜索到了。當然可以通過restful api 和Java api,手動的執行一次refresh操作,就是手動的將buffer中的數據刷入到OS cache之中,讓數據立馬搜索到,只要數據被輸入到OS cache之中,buffer的內容就會被清空了。同時進行的是,數據到shard之後,就會將數據寫入到translog之中,每隔5秒將translog之中的數據持久化到磁盤之中。

C 重複以上的操作,每次一條數據寫入buffer,同時會寫入一條日誌到translog日誌文件之中去,這個translog文件會不斷的變大,當達到一定的程度之後,就會觸發commit操作。

D 將一個commit point寫入到磁盤文件,裏面標識着這個commit point 對應的所有segment file。

E 強行將OS cache 之中的數據都fsync到磁盤文件中去。
解釋:translog的作用:在執行commit之前,所有的數據都是停留在buffer或OS cache之中,無論是buffer或OS cache都是內存,一旦這臺機器死了,內存的數據就會丟失,所以需要將數據對應的操作寫入一個專門的日誌問價之中,一旦機器出現宕機,再次重啓的時候,es會主動的讀取translog之中的日誌文件的數據,恢復到內存buffer和OS cache之中。

F 將現有的translog文件進行清空,然後在重新啓動一個translog,此時commit就算是成功了,默認的是每隔30分鐘進行一次commit,但是如果translog的文件過大,也會觸發commit,整個commit過程就叫做一個flush操作,我們也可以通過ES API,手動執行flush操作,手動將OS cache 的數據fsync到磁盤上面去,記錄一個commit point,清空translog文件。
補充:其實translog的數據也是先寫入到OS cache之中的,默認每隔5秒之中將數據刷新到硬盤中去,也就是說,可能有5秒的數據僅僅停留在buffer或者translog文件的OS cache中,如果此時機器掛了,會丟失5秒的數據,但是這樣的性能比較好,我們也可以將每次的操作都直接fsync到磁盤,但是性能會比較差。

G 如果是刪除操作,commit的時候會產生一個.del文件,裏面講某個doc標記爲delete狀態,那麼搜索的時候,會根據.del文件的狀態,就知道那個文件被刪除了。

 如果是更新操作,就是講原來的doc標識爲delete狀態,然後重新寫入一條數據即可。

I buffer每次更新一次,就會產生一個segment file 文件,所以在默認情況之下,就會產生很多的segment file 文件,將會定期執行merge操作

 每次merge的時候,就會將多個segment file 文件進行合併爲一個,同時將標記爲delete的文件進行刪除,然後將新的segment file 文件寫入到磁盤,這裏會寫一個commit point,標識所有的新的segment file,然後打開新的segment file供搜索使用。

   總之,segment的四個核心概念,refresh,flush,translog、merge 。

 

八 搜索的底層原理

  查詢過程大體上分爲查詢和取回這兩個階段,廣播查詢請求到所有相關分片,並將它們的響應整合成全局排序後的結果集合,這個結果集合會返回給客戶端。

 查詢階段

  A 當一個節點接收到一個搜索請求,這個節點就會變成協調節點,第一步就是將廣播請求到搜索的每一個節點的分片拷貝,查詢請求可以被某一個主分片或某一個副分片處理,協調節點將在之後的請求中輪訓所有的分片拷貝來分攤負載。

  B 每一個分片將會在本地構建一個優先級隊列,如果客戶端要求返回結果排序中從from 名開始的數量爲size的結果集,每一個節點都會產生一個from+size大小的結果集,因此優先級隊列的大小也就是from+size,分片僅僅是返回一個輕量級的結果給協調節點,包括結果級中的每一個文檔的ID和進行排序所需要的信息。

  C 協調節點將所有的結果進行彙總,並進行全局排序,最終得到排序結果。

 取值階段

  A 查詢過程得到的排序結果,標記處哪些文檔是符合要求的,此時仍然需要獲取這些文檔返回給客戶端。

  B 協調節點會確定實際需要的返回的文檔,並向含有該文檔的分片發送get請求,分片獲取的文檔返回給協調節點,協調節點將結果返回給客戶端。

九 倒排索引

倒排索引就建立分詞與文檔之間的映射關係,在倒排索引之中,數據是面向分詞的而不是面向文檔的。

十 在海量數據中怎樣提高效率

A filesystem cache


ES的搜索引擎是嚴重的依賴底層的filesystem cache,如果給filesystem cache更多的內存,儘量讓內存可以容納所有的index segment file 索引數據文件。

B 數據預熱


對於那些你覺得比較熱的數據,經常會有人訪問的數據,最好做一個專門的緩存預熱子系統,就是對熱數據,每隔一段時間,你就提前訪問以下,讓數據進入filesystem cache裏面去,這樣期待下次訪問的時候,性能會更好一些。

C 冷熱分離

關於ES的性能優化,數據拆分,將大量的搜索不到的字段,拆分到別的存儲中去,這個類似於MySQL的分庫分表的垂直拆分。

D document的模型設計

不要在搜索的時候去執行各種複雜的操作,儘量在document模型設計的時候,寫入的時候就完成,另外對於一些複雜的操作,儘量要避免。

E 分頁性能優化

翻頁的時候,翻得越深,每個shard返回的數據越多,而且協調節點處理的時間越長,當然是用scroll,scroll會一次性的生成所有數據的一個快照,然後每次翻頁都是通過移動遊標完成的。 api 只是在一頁一頁的往後翻。

 

參考 

https://segmentfault.com/a/1190000015256970?utm_source=tag-newest

https://blog.csdn.net/liyantianmin/article/details/72973281

https://www.cnblogs.com/leeSmall/p/9220535.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章