ElasticSearch搜索引擎常见面试题总结
一、ElasticSearch基礎:
1、什么是Elasticsearch:
????????Elasticsearch 是基于 Lucene 的 Restful 的分布式實時全文搜索引擎,每個字段都被索引并可被搜索,可以快速存儲、搜索、分析海量的數據。
全文檢索是指對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置。當查詢時,根據事先建立的索引進行查找,并將查找的結果反饋給用戶的檢索方式。這個過程類似于通過字典中的檢索字表查字的過程。
2、Elasticsearch 的基本概念:
(1)index 索引:索引類似于mysql 中的數據庫,Elasticesearch 中的索引是存在數據的地方,包含了一堆有相似結構的文檔數據。
(2)type 類型:類型是用來定義數據結構,可以認為是 mysql 中的一張表,type 是 index 中的一個邏輯數據分類
(3)document 文檔:類似于 MySQL 中的一行,不同之處在于 ES 中的每個文檔可以有不同的字段,但是對于通用字段應該具有相同的數據類型,文檔是es中的最小數據單元,可以認為一個文檔就是一條記錄。
(4)Field 字段:Field是Elasticsearch的最小單位,一個document里面有多個field
(5)shard 分片:單臺機器無法存儲大量數據,es可以將一個索引中的數據切分為多個shard,分布在多臺服務器上存儲。有了shard就可以橫向擴展,存儲更多數據,讓搜索和分析等操作分布到多臺服務器上去執行,提升吞吐量和性能。
(6)replica 副本:任何一個服務器隨時可能故障或宕機,此時 shard 可能會丟失,因此可以為每個 shard 創建多個 replica 副本。replica可以在shard故障時提供備用服務,保證數據不丟失,多個replica還可以提升搜索操作的吞吐量和性能。primary shard(建立索引時一次設置,不能修改,默認5個),replica shard(隨時修改數量,默認1個),默認每個索引10個 shard,5個primary shard,5個replica shard,最小的高可用配置,是2臺服務器。
3、什么是倒排索引:
????????在搜索引擎中,每個文檔都有一個對應的文檔 ID,文檔內容被表示為一系列關鍵詞的集合。例如,某個文檔經過分詞,提取了 20 個關鍵詞,每個關鍵詞都會記錄它在文檔中出現的次數和出現位置。那么,倒排索引就是?關鍵詞到文檔?ID 的映射,每個關鍵詞都對應著一系列的文件,這些文件中都出現了該關鍵詞。有了倒排索引,搜索引擎可以很方便地響應用戶的查詢。
要注意倒排索引的兩個重要細節:
- 倒排索引中的所有詞項對應一個或多個文檔
- 倒排索引中的詞項?根據字典順序升序排列
4、doc_values 的作用:
????????倒排索引也是有缺陷的,假如我們需要對數據做一些排序或聚合操作時,lucene 內部會遍歷提取所有出現在文檔集合的排序字段,然后再次構建一個最終的排好序的文檔集合list,這個步驟的過程全部維持在內存中操作,而且如果排序數據量巨大的話,非常容易就造成內存溢出和性能緩慢。
????????doc_values 就是 es 在構建倒排索引的同時,構建了正排索引,保存了docId到各個字段值的映射,可以看作是以文檔為維度,從而實現根據指定字段進行排序和聚合的功能。另外 doc_values 保存在操作系統的磁盤中,當 doc_values 大于節點的可用內存,ES可以從操作系統頁緩存中加載或彈出,從而避免發生內存溢出的異常,docValues遠小于節點的可用內存,操作系統自然將所有 doc_values 存于內存中(堆外內存),有助于快速訪問。
更多 doc_values 的介紹與使用歡迎閱讀這篇文章:ElasticSearch搜索引擎:doc_values詳細介紹
5、text 和 keyword類型的區別:
????????兩個的區別主要分詞的區別:keyword 類型是不會分詞的,直接根據字符串內容建立倒排索引,keyword類型的字段只能通過精確值搜索到;Text 類型在存入 Elasticsearch 的時候,會先分詞,然后根據分詞后的內容建立倒排索引
6、什么是停頓詞過濾:
停頓詞可以看成是沒有意義的詞,比如“的”、“而”,這類詞沒有必要建立索引
7、query 和 filter 的區別?
(1)query:查詢操作不僅僅會進行查詢,還會計算分值,用于確定相關度;
(2)filter:查詢操作僅判斷是否滿足查詢條件,不會計算任何分值,也不會關心返回的排序問題,同時,filter 查詢的結果可以被緩存,提高性能。
二、ES的寫入流程:
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、寫數據的底層原理:
(1)數據先寫入 memory buffer,然后定時(默認每隔1s)將?memory buffer 中的數據寫入一個新的 segment 文件中,并進入?Filesystem cache(同時清空 memory buffer),這個過程就叫做 refresh;
ES 的近實時性:數據存在 memory?buffer 時是搜索不到的,只有數據被 refresh 到??Filesystem cache 之后才能被搜索到,而 refresh 是每秒一次,?所以稱 es 是近實時的,可以通過手動調用?es 的 api 觸發一次 refresh 操作,讓數據馬上可以被搜索到;
(2)由于?memory?Buffer 和 Filesystem Cache 都是基于內存,假設服務器宕機,那么數據就會丟失,所以 ES 通過 translog 日志文件來保證數據的可靠性,在數據寫入?memory buffer 的同時,將數據寫入 translog 日志文件中,在機器宕機重啟時,es 會自動讀取 translog 日志文件中的數據,恢復到 memory?buffer 和 Filesystem cache 中去。
ES 數據丟失的問題:translog 也是先寫入 Filesystem cache,然后默認每隔 5 秒刷一次到磁盤中,所以默認情況下,可能有 5 秒的數據會僅僅停留在?memory?buffer 或者 translog 文件的 Filesystem cache中,而不在磁盤上,如果此時機器宕機,會丟失 5 秒鐘的數據。也可以將 translog 設置成每次寫操作必須是直接 fsync 到磁盤,但是性能會差很多。
(3)flush 操作:不斷重復上面的步驟,translog 會變得越來越大,當 translog 文件默認每30分鐘或者 閾值超過 512M 時,就會觸發 commit 操作,即 flush操作。
- ① 將 buffer 中的數據 refresh 到 Filesystem Cache?中去,清空 buffer;
- ② 創建一個新的 commit point(提交點),同時強行將 Filesystem Cache 中目前所有的數據都 fsync 到磁盤文件中;
- ③ 刪除舊的?translog 日志文件并創建一個新的?translog 日志文件,此時 commit 操作完成
更多 ES 的數據寫入流程的說明歡迎閱讀這篇文章:ElasticSearch搜索引擎:數據的寫入流程
三、ES的更新和刪除流程:
????????刪除和更新都是寫操作,但是由于 Elasticsearch 中的文檔是不可變的,因此不能被刪除或者改動以展示其變更;所以 ES 利用 .del 文件 標記文檔是否被刪除,磁盤上的每個段都有一個相應的.del 文件
(1)如果是刪除操作,文檔其實并沒有真的被刪除,而是在 .del 文件中被標記為 deleted 狀態。該文檔依然能匹配查詢,但是會在結果中被過濾掉。
(2)如果是更新操作,就是將舊的?doc 標識為 deleted 狀態,然后創建一個新的?doc。
memory?buffer 每 refresh 一次,就會產生一個 segment 文件?,所以默認情況下是 1s 生成一個 segment 文件,這樣下來 segment 文件會越來越多,此時會定期執行 merge。每次 merge 的時候,會將多個 segment 文件合并成一個,同時這里會將標識為 deleted 的 doc 給物理刪除掉,不寫入到新的 segment 中,然后將新的 segment 文件寫入磁盤,這里會寫一個 commit point ,標識所有新的 segment 文件,然后打開 segment 文件供搜索使用,同時刪除舊的 segment 文件
有關segment段合并過程,歡迎閱讀這篇文章:Elasticsearch搜索引擎:ES的segment段合并原理
四、ES的搜索流程:
搜索被執行成一個兩階段過程,即 Query Then Fetch:
1、Query階段:
????????客戶端發送請求到?coordinate node,協調節點將搜索請求廣播到所有的?primary shard 或 replica shard。每個分片在本地執行搜索并構建一個匹配文檔的大小為 from + size 的優先隊列。 每個分片返回各自優先隊列中 所有文檔的 ID 和排序值 給協調節點,由協調節點及逆行數據的合并、排序、分頁等操作,產出最終結果。
2、Fetch階段:
????????協調節點根據 doc id 去各個節點上查詢實際的?document 數據,由協調節點返回結果給客戶端。
- coordinate node 對 doc id 進行哈希路由,將請求轉發到對應的 node,此時會使用 round-robin 隨機輪詢算法,在 primary shard 以及其所有 replica 中隨機選擇一個,讓讀請求負載均衡。
- 接收請求的 node 返回 document 給 coordinate node 。
- coordinate node 返回 document 給客戶端。
????????Query Then Fetch 的搜索類型在文檔相關性打分的時候參考的是本分片的數據,這樣在文檔數量較少的時候可能不夠準確,DFS Query Then Fetch 增加了一個預查詢的處理,詢問 Term 和 Document frequency,這個評分更準確,但是性能會變差。
五、ES在高并發下如何保證讀寫一致性?
(1)對于更新操作:可以通過版本號使用樂觀并發控制,以確保新版本不會被舊版本覆蓋
每個文檔都有一個_version 版本號,這個版本號在文檔被改變時加一。Elasticsearch使用這個 _version 保證所有修改都被正確排序。當一個舊版本出現在新版本之后,它會被簡單的忽略。
利用_version的這一優點確保數據不會因為修改沖突而丟失。比如指定文檔的version來做更改。如果那個版本號不是現在的,我們的請求就失敗了。
(2)對于寫操作,一致性級別支持 quorum/one/all,默認為 quorum,即只有當大多數分片可用時才允許寫操作。但即使大多數可用,也可能存在因為網絡等原因導致寫入副本失敗,這樣該副本被認為故障,分片將會在一個不同的節點上重建。
- one:要求我們這個寫操作,只要有一個primary shard是active活躍可用的,就可以執行
- all:要求我們這個寫操作,必須所有的primary shard和replica shard都是活躍的,才可以執行這個寫操作
- quorum:默認的值,要求所有的shard中,必須是大部分的shard都是活躍的,可用的,才可以執行這個寫操作
(3)對于讀操作,可以設置 replication 為 sync(默認),這使得操作在主分片和副本分片都完成后才會返回;如果設置replication 為 async 時,也可以通過設置搜索請求參數 _preference 為 primary 來查詢主分片,確保文檔是最新版本。
六、ES如何選舉Master節點:
1、Elasticsearch 的分布式原理:
????????Elasticsearch 會對存儲的數據進行切分,將數據劃分到不同的分片上,同時每一個分片會保存多個副本,主要是為了保證分布式環境的高可用。在 Elasticsearch 中,節點是對等的,節點間會選取集群的 Master,由 Master 會負責集群狀態信息的改變,并同步給其他節點。
Elasticsearch 的性能會不會很低:只有建立索引和類型需要經過 Master,數據的寫入有一個簡單的 Routing 規則,可以路由到集群中的任意節點,所以數據寫入壓力是分散在整個集群的。
2、Elasticsearch 如何 選舉 Master:
????????Elasticsearch 的選主是 ZenDiscovery 模塊負責的,主要包含Ping(節點之間通過這個RPC來發現彼此)和 Unicast(單播模塊包含一個主機列表以控制哪些節點需要ping通)這兩部分;
- (1)確認候選主節點的最少投票通過數量,elasticsearch.yml 設置的值 discovery.zen.minimum_master_nodes;
- (2)對所有候選?master 的節點(node.master: true)根據 nodeId 字典排序,每次選舉每個節點都把自己所知道節點排一次序,然后選出第一個(第0位)節點,暫且認為它是master節點。
- (3)如果對某個節點的投票數達到閾值,并且該節點自己也選舉自己,那這個節點就是master。否則重新選舉一直到滿足上述條件。
補充:master節點的職責主要包括集群、節點和索引的管理,不負責文檔級別的管理;data節點可以關閉http功能。
3、Elasticsearch是如何避免腦裂現象:
(1)當集群中 master 候選節點數量不小于3個時(node.master:?true),可以通過設置最少投票通過數量(discovery.zen.minimum_master_nodes),設置超過所有候選節點一半以上來解決腦裂問題,即設置為 (N/2)+1;
(2)當集群 master 候選節點 只有兩個時,這種情況是不合理的,最好把另外一個node.master改成false。如果我們不改節點設置,還是套上面的(N/2)+1公式,此時discovery.zen.minimum_master_nodes應該設置為2。這就出現一個問題,兩個master備選節點,只要有一個掛,就選不出master了
七、建立索引階段性能提升方法:
- (1)使用 SSD 存儲介質
- (2)使用批量請求并調整其大小:每次批量數據 5–15 MB 大是個不錯的起始點。
- (3)如果你在做大批量導入,考慮通過設置 index.number_of_replicas: 0 關閉副本
- (4)如果你的搜索結果不需要近實時的準確度,考慮把每個索引的 index.refresh_interval 改到30s
- (5)段和合并:Elasticsearch 默認值是 20 MB/s。但如果用的是 SSD,可以考慮提高到 100–200 MB/s。如果你在做批量導入,完全不在意搜索,你可以徹底關掉合并限流。
- (6)增加 index.translog.flush_threshold_size 設置,從默認的 512 MB 到更大一些的值,比如 1 GB
八、ES的深度分頁與滾動搜索scroll
(1)深度分頁:
????????深度分頁其實就是搜索的深淺度,比如第1頁,第2頁,第10頁,第20頁,是比較淺的;第10000頁,第20000頁就是很深了。搜索得太深,就會造成性能問題,會耗費內存和占用cpu。而且es為了性能,他不支持超過一萬條數據以上的分頁查詢。那么如何解決深度分頁帶來的問題,我們應該避免深度分頁操作(限制分頁頁數),比如最多只能提供100頁的展示,從第101頁開始就沒了,畢竟用戶也不會搜的那么深。
(2)滾動搜索:
????????一次性查詢1萬+數據,往往會造成性能影響,因為數據量太多了。這個時候可以使用滾動搜索,也就是 scroll。 滾動搜索可以先查詢出一些數據,然后再緊接著依次往下查詢。在第一次查詢的時候會有一個滾動id,相當于一個錨標記 ,隨后再次滾動搜索會需要上一次搜索滾動id,根據這個進行下一次的搜索請求。每次搜索都是基于一個歷史的數據快照,查詢數據的期間,如果有數據變更,那么和搜索是沒有關系的。
相關閱讀:
Spring常見面試題總結
SpringMVC常見面試題總結
Mybatis常見面試題總結
MySQL常見面試題總結
Redis常見面試題總結
RabbitMQ消息隊列常見面試題總結
ElasticSearch搜索引擎常見面試題總結
計算機網絡常見面試題總結
操作系統常見面試題總結
Java基礎、集合、多線程常見面試題總結
Java虛擬機常見面試題總結
Java常見設計模式總結
海量數據處理的方法總結
總結
以上是生活随笔為你收集整理的ElasticSearch搜索引擎常见面试题总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL数据库常见面试题总结
- 下一篇: ElasticSearch搜索引擎:常用