es分佈式架構原理
elasticsearch設計的理念就是分佈式搜索引擎,底層實現仍是基於Lucene的,核心思想是在多態機器上啓動多個es進程實例,組成一個es集羣。一下是es的幾個概念:node
- 接近實時
es是一個接近實時的搜索平臺,這就意味着,從索引一個文檔直到文檔可以被搜索到有一個輕微的延遲
- 集羣(cluster)
一個集羣有多個節點(服務器)組成,經過全部的節點一塊兒保存你的所有數據而且經過聯合索引和搜索功能的節點的集合,每個集羣有一個惟一的名稱標識
- 節點(node)
一個節點就是一個單一的服務器,是你的集羣的一部分,存儲數據,而且參與集羣和搜索功能,一個節點能夠經過配置特定的名稱來加入特定的集羣,在一個集羣中,你想啓動多少個節點就能夠啓動多少個節點。
- 索引(index)
一個索引就是還有某些共有特性的文檔的集合,一個索引被一個名稱惟一標識,而且這個名稱被用於索引經過文檔去執行搜索,更新和刪除操做。
- 類型(type)
type 在6.0.0已經不同意使用
- 文檔(document)
一個文檔是一個基本的搜索單元
總結:
es中,存儲數據的基本單位就是索引,好比說es中存儲了一些訂單系統的銷售數據,就因該在es中建立一個索引,order—index,全部的銷售數據就會都寫到這個索引裏面去,一個索引就像數據庫。而type就至關於每一張表,
一個index裏面能夠有多個type,而mapping就至關於表的結構定義,定義了什麼字段類型等,你往index的一個type裏添加一行數據就叫作一個document,每個document有多個filed,每個filed就表明這個document的一個字段的值。算法
- 分片(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寫入數據的過程
- 客戶端選擇一個node發送請求過去,這個node就是coordinating node (協調節點)
- coordinating node,對document進行路由,將請求轉發給對應的node
- 實際上的node上的primary shard處理請求,而後將數據同步到replica node
- coordinating node,若是發現primary node和全部的replica node都搞定以後,就會返回請求到客戶端
es讀數據過程
查詢,GET某一條的數據,寫入某個document,這個document會自動給你分配一個全局的惟一ID,同時跟住這個ID進行hash路由到對應的primary shard上面去,固然也能夠手動的設置IDapi
- 客戶端發送任何一個請求到任意一個node,成爲coordinate node
- coordinate node 對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪訓算法,在primary shard 以及全部的replica中隨機選擇一個,讓讀請求負載均衡,
- 接受請求的node,返回document給coordinate note
- coordinate node返回給客戶端
es搜索數據過程
- 客戶端發送一個請求給coordinate node
- 協調節點將搜索的請求轉發給全部的shard對應的primary shard 或replica shard
- query phase:每個shard 將本身搜索的結果(其實也就是一些惟一標識),返回給協調節點,有協調節點進行數據的合併,排序,分頁等操做,產出最後的結果
- fetch phase ,接着由協調節點,根據惟一標識去各個節點進行拉去數據,最總返回給客戶端
寫入數據的底層原理
- 數據先寫入到buffer裏面,在buffer裏面的數據時搜索不到的,同時將數據寫入到translog日誌文件之中
- 若是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之中的數據持久化到磁盤之中
- 重複以上的操做,每次一條數據寫入buffer,同時會寫入一條日誌到translog日誌文件之中去,這個translog文件會不斷的變大,當達到必定的程度以後,就會觸發commit操做。
- 將一個commit point寫入到磁盤文件,裏面標識着這個commit point 對應的全部segment file
- 強行將OS cache 之中的數據都fsync到磁盤文件中去。
解釋:translog的做用:在執行commit以前,全部的而數據都是停留在buffer或OS cache之中,不管buffer或OS cache都是內存,一旦這臺機器死了,內存的數據就會丟失,因此須要將數據對應的操做寫入一個專門的日誌問價之中,一旦機器出現宕機,再次重啓的時候,es會主動的讀取translog之中的日誌文件的數據,恢復到內存buffer和OS cache之中。
- 將現有的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到磁盤,可是性能會比較差。
- 若是時刪除操做,commit的時候會產生一個.del文件,裏面講某個doc標記爲delete狀態,那麼搜索的時候,會根據.del文件的狀態,就知道那個文件被刪除了。
- 若是時更新操做,就是講原來的doc標識爲delete狀態,而後從新寫入一條數據便可。
- buffer每次更新一次,就會產生一個segment file 文件,因此在默認狀況之下,就會產生不少的segment file 文件,將會按期執行merge操做
- 每次merge的時候,就會將多個segment file 文件進行合併爲一個,同時將標記爲delete的文件進行刪除,而後將新的segment file 文件寫入到磁盤,這裏會寫一個commit point,標識全部的新的segment file,而後打開新的segment file供搜索使用。
總之,segment的四個核心概念,refresh,flush,translog、merge緩存
搜索的底層原理
查詢過程大致上分爲查詢和取回這兩個階段,廣播查詢請求到全部相關分片,並將它們的響應整合成全局排序後的結果集合,這個結果集合會返回給客戶端。性能優化
-
查詢階段服務器
- 當一個節點接收到一個搜索請求,這這個節點就會變成協調節點,第一步就是將廣播請求到搜索的每個節點的分片拷貝,查詢請求能夠被某一個主分片或某一個副分片處理,協調節點將在以後的請求中輪訓全部的分片拷貝來分攤負載。
- 每個分片將會在本地構建一個優先級隊列,若是客戶端要求返回結果排序中從from 名開始的數量爲size的結果集,每個節點都會產生一個from+size大小的結果集,所以優先級隊列的大小也就是from+size,分片僅僅是返回一個輕量級的結果給協調節點,包括結果級中的每個文檔的ID和進行排序所須要的信息。
- 協調節點將會將全部的結果進行彙總,並進行全局排序,最總獲得排序結果。
-
取值階段restful
- 查詢過程獲得的排序結果,標記處哪些文檔是符合要求的,此時仍然須要獲取這些文檔返回給客戶端
- 協調節點會肯定實際須要的返回的文檔,並向含有該文檔的分片發送get請求,分片獲取的文檔返回給協調節點,協調節點將結果返回給客戶端。
倒排索引
倒排索引就創建分詞與文檔之間的映射關係,在倒排索引之中,數據時面向分詞的而不是面向文檔的。網絡
在海量數據中怎樣提升效率
- filesystem cache
ES的搜索引擎是嚴重的依賴底層的filesystem cache,若是給filesystem cache更多的內存,儘可能讓內存能夠容納全部的index segment file 索引數據文件
- 數據預熱
對於那些你以爲比較熱的數據,常常會有人訪問的數據,最好作一個專門的緩存預熱子系統,就是對熱數據,每隔一段時間,你就提早訪問如下,讓數據進入filesystem cache裏面去,這樣期待下次訪問的時候,性能會更好一些。
- 冷熱分離
關於ES的性能優化,數據拆分,將大量的搜索不到的字段,拆分到別的存儲中去,這個相似於MySQL的分庫分表的垂直才分。架構
- document的模型設計
不要在搜索的時候去執行各類複雜的操做,儘可能在document模型設計的時候,寫入的時候就完成了,另外對於一些複雜的操做,儘可能要避免
- 分頁性能優化
翻頁的時候,翻得越深,每一個shard返回的數據越多,並且協調節點處理的時間越長,固然是用scroll,scroll會一次性的生成全部數據的一個快照,而後每次翻頁都是經過移動遊標完成的。 api 只是在一頁一頁的日後翻