11 分散式搜尋引擎寫入和查詢的工作流程是什麼樣的?
目錄
(4)搜尋的底層原理,倒排索引,畫圖說明傳統資料庫和倒排索引的區別
1、面試題
es寫入資料的工作原理是什麼啊?es查詢資料的工作原理是什麼啊?
2、面試官心理分析
問這個,其實面試官就是要看看你瞭解不瞭解es的一些基本原理,因為用es無非就是寫入資料,搜尋資料。你要是不明白你發起一個寫入和搜尋請求的時候,es在幹什麼,那你真的就是。。。。
對es基本就是個黑盒,你還能幹啥?你唯一能幹的就是用es的api讀寫資料了。。。要是出點什麼問題,你啥都不知道,那還能指望你什麼呢?是不是。。
3、面試題剖析
(1)es寫資料過程
1)客戶端選擇一個node傳送請求過去,這個node就是coordinating node(協調節點)
2)coordinating node,對document進行路由,將請求轉發給對應的node(有primary shard)
3)實際的node上的primary shard處理請求,然後將資料同步到replica node
4)coordinating node,如果發現primary node和所有replica node都搞定之後,就返回響應結果給客戶端
(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去查詢
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操作:1、寫commit point;2、將os cache資料fsync強刷到磁碟上去;3、清空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。