(1)es寫數據過程java
1)客戶端選擇一個node發送請求過去,這個node就是coordinating node(協調節點)node
2)coordinating node,對document進行路由,將請求轉發給對應的node(有primary shard)面試
3)實際的node上的primary shard處理請求,而後將數據同步到replica node算法
4)coordinating node,若是發現primary node和全部replica node都搞定以後,就返回響應結果給客戶端數據庫
(2)es讀數據過程api
查詢,GET某一條數據,寫入了某個document,這個document會自動給你分配一個全局惟一的id,doc id,同時也是根據doc id進行hash路由到對應的primary shard上面去。也能夠手動指定doc id,好比用訂單id,用戶id。緩存
你能夠經過doc id來查詢,會根據doc id進行hash,判斷出來當時把doc id分配到了哪一個shard上面去,從那個shard去查詢restful
1)客戶端發送請求到任意一個node,成爲coordinate node負載均衡
2)coordinate node對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪詢算法,在primary shard以及其全部replica中隨機選擇一個,讓讀請求負載均衡性能
3)接收請求的node返回document給coordinate node
4)coordinate node返回document給客戶端
(3)es搜索數據過程
es最強大的是作全文檢索,就是好比你有三條數據
java真好玩兒啊
java好難學啊
j2ee特別牛
你根據java關鍵詞來搜索,將包含java的document給搜索出來
es就會給你返回:java真好玩兒啊,java好難學啊
1)客戶端發送請求到一個coordinate node
2)協調節點將搜索請求轉發到全部的shard對應的primary shard或replica shard也能夠
3)query phase:每一個shard將本身的搜索結果(其實就是一些doc id),返回給協調節點,由協調節點進行數據的合併、排序、分頁等操做,產出最終結果
4)fetch phase:接着由協調節點,根據doc id去各個節點上拉取實際的document數據,最終返回給客戶端
(4)搜索的底層原理,倒排索引,畫圖說明傳統數據庫和倒排索引的區別
(5)寫數據底層原理
1)先寫入buffer,在buffer裏的時候數據是搜索不到的;同時將數據寫入translog日誌文件
2)若是buffer快滿了,或者到必定時間,就會將buffer數據refresh到一個新的segment file中,可是此時數據不是直接進入segment file的磁盤文件的,而是先進入os cache的。這個過程就是refresh。
每隔1秒鐘,es將buffer中的數據寫入一個新的segment file,每秒鐘會產生一個新的磁盤文件,segment file,這個segment file中就存儲最近1秒內buffer中寫入的數據
可是若是buffer裏面此時沒有數據,那固然不會執行refresh操做咯,每秒建立換一個空的segment file,若是buffer裏面有數據,默認1秒鐘執行一次refresh操做,刷入一個新的segment file中
操做系統裏面,磁盤文件其實都有一個東西,叫作os cache,操做系統緩存,就是說數據寫入磁盤文件以前,會先進入os cache,先進入操做系統級別的一個內存緩存中去
只要buffer中的數據被refresh操做,刷入os cache中,就表明這個數據就能夠被搜索到了
爲何叫es是準實時的?NRT,near real-time,準實時。默認是每隔1秒refresh一次的,因此es是準實時的,由於寫入的數據1秒以後才能被看到。
能夠經過es的restful api或者java api,手動執行一次refresh操做,就是手動將buffer中的數據刷入os cache中,讓數據立馬就能夠被搜索到。
只要數據被輸入os cache中,buffer就會被清空了,由於不須要保留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的,默認每隔5秒刷一次到磁盤中去,因此默認狀況下,可能有5秒的數據會僅僅停留在buffer或者translog文件的os cache中,若是此時機器掛了,會丟失5秒鐘的數據。可是這樣性能比較好,最多丟5秒的數據。也能夠將translog設置成每次寫操做必須是直接fsync到磁盤,可是性能會差不少。
實際上你在這裏,若是面試官沒有問你es丟數據的問題,你能夠在這裏給面試官炫一把,你說,其實es第一是準實時的,數據寫入1秒後能夠搜索到;可能會丟失數據的,你的數據有5秒的數據,停留在buffer、translog os cache、segment file os cache中,有5秒的數據不在磁盤上,此時若是宕機,會致使5秒的數據丟失。
若是你但願必定不能丟失數據的話,你能夠設置個參數,官方文檔,百度一下。每次寫入一條數據,都是寫入buffer,同時寫入磁盤上的translog,可是這會致使寫性能、寫入吞吐量會降低一個數量級。原本一秒鐘能夠寫2000條,如今你一秒鐘只能寫200條,都有可能。
10)若是是刪除操做,commit的時候會生成一個.del文件,裏面將某個doc標識爲deleted狀態,那麼搜索的時候根據.del文件就知道這個doc被刪除了
11)若是是更新操做,就是將原來的doc標識爲deleted狀態,而後新寫入一條數據
12)buffer每次refresh一次,就會產生一個segment file,因此默認狀況下是1秒鐘一個segment file,segment file會愈來愈多,此時會按期執行merge
13)每次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。