elasticsearch面試必考親身經歷的問題)

      網友投稿 1292 2022-05-28

      面試題

      es 寫入數據的工作原理是什么啊?es 查詢數據的工作原理是什么啊?底層的 lucene 介紹一下唄?倒排索引了解嗎?

      面試官心理分析

      問這個,其實面試官就是要看看你了解不了解 es 的一些基本原理,因為用 es 無非就是寫入數據,搜索數據。你要是不明白你發起一個寫入和搜索請求的時候,es 在干什么,那你真的是…

      對 es 基本就是個黑盒,你還能干啥?你唯一能干的就是用 es 的 api 讀寫數據了。要是出點什么問題,你啥都不知道,那還能指望你什么呢?

      面試題剖析

      es 寫數據過程

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

      coordinating node 對 document 進行路由,將請求轉發給對應的 node(有 primary shard)。

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

      coordinating node 如果發現 primary node 和所有 replica node 都搞定之后,就返回響應結果給客戶端。

      es 讀數據過程

      可以通過 doc id 來查詢,會根據 doc id 進行 hash,判斷出來當時把 doc id 分配到了哪個 shard 上面去,從那個 shard 去查詢。

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

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

      接收請求的 node 返回 document 給 coordinate node。

      coordinate node 返回 document 給客戶端。

      es 搜索數據過程

      es 最強大的是做全文檢索,就是比如你有三條數據:

      java真好玩兒啊 java好難學啊 j2ee特別牛

      1

      2

      3

      4

      你根據 java 關鍵詞來搜索,將包含 java的 document 給搜索出來。es 就會給你返回:java 真好玩兒啊,java 好難學啊。

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

      協調節點將搜索請求轉發到所有的 shard 對應的 primary shard 或 replica shard,都可以。

      query phase:每個 shard 將自己的搜索結果(其實就是一些 doc id)返回給協調節點,由協調節點進行數據的合并、排序、分頁等操作,產出最終結果。

      fetch phase:接著由協調節點根據 doc id 去各個節點上拉取實際的 document 數據,最終返回給客戶端。

      寫請求是寫入 primary shard,然后同步給所有的 replica shard;讀請求可以從 primary shard 或 replica shard 讀取,采用的是隨機輪詢算法。

      寫數據底層原理

      先寫入內存 buffer,在 buffer 里的時候數據是搜索不到的;同時將數據寫入 translog 日志文件。

      如果 buffer 快滿了,或者到一定時間,就會將內存 buffer 數據 refresh 到一個新的 segment file 中,但是此時數據不是直接進入 segment file 磁盤文件,而是先進入 os cache 。這個過程就是 refresh。

      每隔 1 秒鐘,es 將 buffer 中的數據寫入一個新的 segment file,每秒鐘會產生一個新的磁盤文件 segment file,這個 segment file 中就存儲最近 1 秒內 buffer 中寫入的數據。

      但是如果 buffer 里面此時沒有數據,那當然不會執行 refresh 操作,如果 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 里面已經持久化到磁盤去一份了。

      重復上面的步驟,新的數據不斷進入 buffer 和 translog,不斷將 buffer 數據寫入一個又一個新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。隨著這個過程推進,translog 會變得越來越大。當 translog 達到一定長度的時候,就會觸發 commit 操作。

      commit 操作發生第一步,就是將 buffer 中現有數據 refresh 到 os cache 中去,清空 buffer。然后,將一個 commit point寫入磁盤文件,里面標識著這個 commit point 對應的所有 segment file,同時強行將 os cache 中目前所有的數據都 fsync 到磁盤文件中去。最后清空 現有 translog 日志文件,重啟一個 translog,此時 commit 操作完成。

      這個 commit 操作叫做 flush。默認 30 分鐘自動執行一次 flush,但如果 translog 過大,也會觸發 flush。flush 操作就對應著 commit 的全過程,我們可以通過 es api,手動執行 flush 操作,手動將 os cache 中的數據 fsync 強刷到磁盤上去。

      translog 日志文件的作用是什么?你執行 commit 操作之前,數據要么是停留在 buffer 中,要么是停留在 os cache 中,無論是 buffer 還是 os cache 都是內存,一旦這臺機器死了,內存中的數據就全丟了。所以需要將數據對應的操作寫入一個專門的日志文件 translog 中,一旦此時機器宕機,再次重啟的時候,es 會自動讀取 translog 日志文件中的數據,恢復到內存 buffer 和 os cache 中去。

      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 秒的數據丟失。

      總結一下,數據先寫入內存 buffer,然后每隔 1s,將數據 refresh 到 os cache,到了 os cache 數據就能被搜索到(所以我們才說 es 從寫入到能被搜索到,中間有 1s 的延遲)。每隔 5s,將數據寫入 translog 文件(這樣如果機器宕機,內存數據全沒,最多會有 5s 的數據丟失),translog 大到一定程度,或者默認每隔 30mins,會觸發 commit 操作,將緩沖區的數據都 flush 到 segment file 磁盤文件中。

      數據寫入 segment file 之后,同時就建立好了倒排索引。

      刪除 / 更新數據底層原理

      如果是刪除操作,commit 的時候會生成一個 .del 文件,里面將某個 doc 標識為 deleted 狀態,那么搜索的時候根據 .del 文件就知道這個 doc 是否被刪除了。

      如果是更新操作,就是將原來的 doc 標識為 deleted 狀態,然后新寫入一條數據。

      buffer 每 refresh 一次,就會產生一個 segment file,所以默認情況下是 1 秒鐘一個 segment file,這樣下來 segment file 會越來越多,此時會定期執行 merge。每次 merge 的時候,會將多個 segment file 合并成一個,同時這里會將標識為 deleted 的 doc 給物理刪除掉,然后將新的 segment file 寫入磁盤,這里會寫一個 commit point,標識所有新的 segment file,然后打開 segment file 供搜索使用,同時刪除舊的 segment file。

      底層 lucene

      簡單來說,lucene 就是一個 jar 包,里面包含了封裝好的各種建立倒排索引的算法代碼。我們用 Java 開發的時候,引入 lucene jar,然后基于 lucene 的 api 去開發就可以了。

      通過 lucene,我們可以將已有的數據建立索引,lucene 會在本地磁盤上面,給我們組織索引的數據結構。

      倒排索引

      elasticsearch面試必考(親身經歷的問題)

      在搜索引擎中,每個文檔都有一個對應的文檔 ID,文檔內容被表示為一系列關鍵詞的集合。例如,文檔 1 經過分詞,提取了 20 個關鍵詞,每個關鍵詞都會記錄它在文檔中出現的次數和出現位置。

      那么,倒排索引就是關鍵詞到文檔 ID 的映射,每個關鍵詞都對應著一系列的文件,這些文件中都出現了關鍵詞。

      舉個栗子。

      有以下文檔:

      對文檔進行分詞之后,得到以下倒排索引。

      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-o4zR8RXN-1645102240094)(https://mmbiz.qpic.cn/mmbiz_jpg/XA3sPCPib1l4ZEiaVvHS7Fk69FicVLrxfy9icuk2abhGViaejABVias1GMibiaZl3IgQH00LicwNRAl8cLRmh63mfSic1Vbg/640?wx_fmt=jpeg)]

      另外,實用的倒排索引還可以記錄更多的信息,比如文檔頻率信息,表示在文檔集合中有多少個文檔包含某個單詞。

      那么,有了倒排索引,搜索引擎可以很方便地響應用戶的查詢。比如用戶輸入查詢 Facebook,搜索系統查找倒排索引,從中讀出包含這個單詞的文檔,這些文檔就是提供給用戶的搜索結果。

      要注意倒排索引的兩個重要細節:

      倒排索引中的所有詞項對應一個或多個文檔

      倒排索引中的詞項根據字典順序升序排列

      上面只是一個簡單的栗子,并沒有嚴格按照字典順序升序排列。

      Elasticsearch Java 實時流計算服務 CS

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:MySQL系列之事務日志Redo log學習筆記
      下一篇:DevOps進階(十一)xcopy提示“目標**是文件名還是目錄名“?
      相關文章
      2020亚洲男人天堂精品| 亚洲精品天堂成人片?V在线播放| 亚洲国产精品13p| 亚洲色欲色欲www| 91天堂素人精品系列全集亚洲| 亚洲国产精品成人精品无码区| 久久精品亚洲男人的天堂| 色噜噜的亚洲男人的天堂| 亚洲av无码一区二区三区天堂| 亚洲中文无码mv| 亚洲中文字幕无码中文| 国产精品亚洲精品观看不卡| 亚洲校园春色另类激情| 亚洲高清一区二区三区| 亚洲人成人网毛片在线播放| 国产精品高清视亚洲一区二区| 国产色在线|亚洲| 在线综合亚洲欧洲综合网站| 亚洲日本一线产区和二线产区对比| 中文字幕在线观看亚洲日韩| 最新亚洲春色Av无码专区| 亚洲中文字幕久久无码| 亚洲变态另类一区二区三区| 亚洲Aⅴ在线无码播放毛片一线天 亚洲avav天堂av在线网毛片 | 国产亚洲精品2021自在线| 亚洲?V无码乱码国产精品| 亚洲国产综合人成综合网站| 亚洲一区视频在线播放| 在线精品亚洲一区二区小说| 国产精品亚洲精品日韩已满| 亚洲AV人人澡人人爽人人夜夜| 久久精品国产亚洲av高清漫画| 亚洲国产精品综合久久网各| 亚洲精品国产精品国自产网站 | 国产亚洲精午夜久久久久久| 亚洲大尺度无码专区尤物| 精品亚洲成a人片在线观看少妇| 亚洲免费人成视频观看| 亚洲精品国产av成拍色拍| 亚洲AV网站在线观看| 亚洲熟妇av一区二区三区|