1. 程式人生 > 其它 >【ElasticSearch面試】10道不得不會的ElasticSearch面試題

【ElasticSearch面試】10道不得不會的ElasticSearch面試題

以下是 ElasticSearch 面試題,相信大家都會有種及眼熟又陌生的感覺、看過可能在短暫的面試後又馬上忘記了。JavaPub在這裡整理這些容易忘記的重點知識及解答建議收藏,經常溫習查閱

評論區見

關於es的面試,建議使用名詞用官方語言描述會更準確。

@

目錄

1. 說說你們公司 es 的叢集架構,索引資料大小,分片有多少,以及一些調優手段 。

節點數、分片數、副本數,儘量根據自己公司使用情況回答,當然適當放大也可行。

調優手段是現在很常見的面試題,下面這幾種調優手段一定要了解懂。當然,下面的每一條都可以當做調優的一部分。

設計調優

參考:
https://www.cnblogs.com/sanduzxcvbnm/p/12084012.html

a. 根據業務增量需求,採取基於日期模板建立索引,通過 rollover API 滾動索引;(rollover API我會單獨寫一個程式碼案例做講解,公眾號:JavaPub)
b. 使用別名進行索引管理;(es的索引名不能改變,提供的別名機制使用非常廣泛。)
c. 每天凌晨定時對索引做force_merge操作,以釋放空間;
d. 採取冷熱分離機制,熱資料儲存到SSD,提高檢索效率;冷資料定期進行shrink操作,以縮減儲存;
e. 採取curator進行索引的生命週期管理;
f. 僅針對需要分詞的欄位,合理的設定分詞器;
g. Mapping階段充分結合各個欄位的屬性,是否需要檢索、是否需要儲存等。

進100+原創文章:https://gitee.com/rodert/JavaPub

寫入調優

  1. 寫入前副本數設定為0;
  2. 寫入前關閉refresh_interval設定為-1,禁用重新整理機制;
  3. 寫入過程中:採取bulk批量寫入;
  4. 寫入後恢復副本數和重新整理間隔;
  5. 儘量使用自動生成的id。

查詢調優

  1. 禁用wildcard;(萬用字元模式,類似於%like%)
  2. 禁用批量terms(成百上千的場景);
  3. 充分利用倒排索引機制,能keyword型別儘量keyword;
  4. 資料量大時候,可以先基於時間敲定索引再檢索;
  5. 設定合理的路由機制。

2. elasticsearch 的倒排索引是什麼

倒排索引也就是單詞到文件的對映,當然不只是存裡文件id這麼簡單。還包括:詞頻(TF,Term Frequency)、偏移量(offset)、位置(Posting)。

3. elasticsearch 是如何實現 master 選舉的

ElasticSearch 的選主是 ZenDiscovery 模組負責,原始碼分析將首發在。 https://gitee.com/rodert/JavaPub

  1. 對所有可以成為 Master 的節點(node.master: true)根據 nodeId 排序,每次選舉每個節點都把自己所知道節點排一次序,然後選出第一個(第0位)節點,暫且認為它是 Master 節點。
  2. 如果對某個節點的投票數達到一定的值(可以成為master節點數n/2+1)並且該節點自己也選舉自己,那這個節點就是master。否則重新選舉。
    (當然也可以自己設定一個值,最小值設定為超過能成為Master節點的n/2+1,否則會出現腦裂問題。discovery.zen.minimum_master_nodes)

4. 描述一下 Elasticsearch 索引文件的過程

  1. 客戶端向 Node 1 傳送新建、索引或者刪除請求。
  2. 節點使用文件的 _id 確定文件屬於分片 0 。請求會被轉發到 Node 3,因為分片 0 的主分片目前被分配在 Node 3 上。
  3. Node 3 在主分片上面執行請求。如果成功了,它將請求並行轉發到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都報告成功, Node 3 將向協調節點報告成功,協調節點向客戶端報告成功。

一圖勝千文,記住這幅圖,上面是文件在節點間分發的過程,接著說一下文件從接收到寫入磁碟過程。
協調節點預設使用文件 ID 參與計算(也支援通過 routing),以便為路由提供合適的分片。

shard = hash(document_id) % (num_of_primary_shards)

  1. 當分片所在的節點接收到來自協調節點的請求後,會將請求寫入到 MemoryBuffer,然後定時(預設是每隔 1 秒)寫入到 Filesystem Cache,這個從 MomeryBuffer 到 Filesystem Cache 的過程就叫做 refresh;
  2. 當然在某些情況下,存在 Momery Buffer 和 Filesystem Cache 的資料可能會丟失,ES 是通過 translog 的機制來保證資料的可靠性的。其實現機制是接收到請求後,同時也會寫入到 translog 中,當 Filesystem cache 中的資料寫入到磁碟中時,才會清除掉,這個過程叫做 flush;
  3. 在 flush 過程中,記憶體中的緩衝將被清除,內容被寫入一個新段,段的 fsync將建立一個新的提交點,並將內容重新整理到磁碟,舊的 translog 將被刪除並開始一個新的 translog。
  4. flush 觸發的時機是定時觸發(預設 30 分鐘)或者 translog 變得太大(預設為 512M)時;
1. translog 可以理解為就是一個檔案,一直追加。
2. MemoryBuffer 應用快取。
3. Filesystem Cache 系統緩衝區。

延伸閱讀:Lucene 的 Segement:

  1. Lucene 索引是由多個段組成,段本身是一個功能齊全的倒排索引。
  2. 段是不可變的,允許 Lucene 將新的文件增量地新增到索引中,而不用從頭重建索引。
  3. 對於每一個搜尋請求而言,索引中的所有段都會被搜尋,並且每個段會消耗CPU 的時鐘周、檔案控制代碼和記憶體。這意味著段的數量越多,搜尋效能會越低。
  4. 為了解決這個問題,Elasticsearch 會合並小段到一個較大的段,提交新的合併段到磁碟,並刪除那些舊的小段。

5. 詳細描述一下 Elasticsearch 搜尋的過程?

es作為一個分散式的儲存和檢索系統,每個文件根據 _id 欄位做路由分發被轉發到對應的shard上。

搜尋執行階段過程分倆個部分,我們稱之為 Query Then Fetch。

5.1 query-查詢階段

當一個search請求發出的時候,這個query會被廣播到索引裡面的每一個shard(主shard或副本shard),每個shard會在本地執行查詢請求後會生成一個命中文件的優先順序佇列。

這個佇列是一個排序好的top N資料的列表,它的size等於from+size的和,也就是說如果你的from是10,size是10,那麼這個佇列的size就是20,所以這也是為什麼深度分頁不能用from+size這種方式,因為from越大,效能就越低。

es裡面分散式search的查詢流程如下:

查詢階段包含以下三個步驟:

  1. 客戶端傳送一個 search 請求到 Node 3 , Node 3 會建立一個大小為 from + size 的空優先佇列。
  2. Node 3 將查詢請求轉發到索引的每個主分片或副本分片中。每個分片在本地執行查詢並新增結果到大小為 from + size 的本地有序優先佇列中。
  3. 每個分片返回各自優先佇列中所有文件的 ID 和排序值給協調節點,也就是 Node 3 ,它合併這些值到自己的優先佇列中來產生一個全域性排序後的結果列表。

5.2 fetch - 讀取階段 / 取回階段


分散式階段由以下步驟構成:

  1. 協調節點辨別出哪些文件需要被取回並向相關的分片提交多個 GET 請求。
  2. 每個分片載入並 豐富 文件,如果有需要的話,接著返回文件給協調節點。
  3. 一旦所有的文件都被取回了,協調節點返回結果給客戶端。

協調節點首先決定哪些文件 確實 需要被取回。例如,如果我們的查詢指定了 { "from": 90, "size": 10 } ,最初的90個結果會被丟棄,只有從第91個開始的10個結果需要被取回。這些文件可能來自和最初搜尋請求有關的一個、多個甚至全部分片。

協調節點給持有相關文件的每個分片建立一個 multi-get request ,併發送請求給同樣處理查詢階段的分片副本。

分片載入文件體-- _source 欄位—​如果有需要,用元資料和 search snippet highlighting 豐富結果文件。 一旦協調節點接收到所有的結果文件,它就組裝這些結果為單個響應返回給客戶端。

拓展閱讀:
深翻頁(Deep Pagination)
---
先查後取的過程支援用 from 和 size 引數分頁,但是這是 有限制的 。 要記住需要傳遞資訊給協調節點的每個分片必須先建立一個 from + size 長度的佇列,協調節點需要根據 number_of_shards * (from + size) 排序文件,來找到被包含在 size 裡的文件。

取決於你的文件的大小,分片的數量和你使用的硬體,給 10,000 到 50,000 的結果文件深分頁( 1,000 到 5,000 頁)是完全可行的。但是使用足夠大的 from 值,排序過程可能會變得非常沉重,使用大量的CPU、記憶體和頻寬。因為這個原因,我們強烈建議你不要使用深分頁。

實際上, “深分頁” 很少符合人的行為。當2到3頁過去以後,人會停止翻頁,並且改變搜尋標準。會不知疲倦地一頁一頁的獲取網頁直到你的服務崩潰的罪魁禍首一般是機器人或者web spider。

如果你 確實 需要從你的叢集取回大量的文件,你可以通過用 scroll 查詢禁用排序使這個取回行為更有效率,我們會在 later in this chapter 進行討論。
注:https://www.elastic.co/guide/cn/elasticsearch/guide/current/scroll.html

6. Elasticsearch 在部署時,對 Linux 的設定有哪些優化方法

  1. 關閉快取swap;

原因:大多數作業系統會將記憶體使用到檔案系統快取,會將應用程式未用到的記憶體交換出去。會導致jvm的堆記憶體交換到磁碟上。交換會導致效能問題。會導致記憶體垃圾回收延長。會導致叢集節點響應時間變慢,或者從叢集中斷開。

  1. 堆記憶體設定為:Min(節點記憶體/2, 32GB);

  2. 設定最大檔案控制代碼數;

後倆點不懂可以先說有一定了解,關注JavaPub會做詳細講解。

  1. 調整執行緒池和佇列大小

  2. 磁碟儲存 raid 方式——儲存有條件使用 RAID6,增加單節點效能以及避免單節點儲存故障。

https://www.elastic.co/cn/blog/how-to-design-your-elasticsearch-data-storage-architecture-for-scale#raid56

7. Elasticsearch 中的節點(比如共 20 個),其中的 10 個選了一個 master,另外 10 個選了另一個 master,怎麼辦?

  1. 當叢集 master 候選數量不小於 3 個時,可以通過設定最少投票通過數量(discovery.zen.minimum_master_nodes)超過所有候選節點一半以上來解決腦裂問題;

  2. 當候選數量為兩個時,只能修改為唯一的一個 master 候選,其他作為 data節點,避免腦裂問題。

8. 客戶端在和叢集連線時,如何選擇特定的節點執行請求的?

client 遠端連線連線一個 elasticsearch 叢集。它並不加入到叢集中,只是獲得一個或者多個初始化的地址,並以輪詢的方式與這些地址進行通訊。

9. 詳細描述一下 Elasticsearch 更新和刪除文件的過程。

  1. 刪除和更新也都是寫操作,但是 Elasticsearch 中的文件是不可變的,因此不能被刪除或者改動以展示其變更;(根本原因是底層lucene的segment段檔案不可更新刪除)
  2. 磁碟上的每個段都有一個相應的 .del 檔案。當刪除請求傳送後,文件並沒有真 的被刪除,而是在 .del 檔案中被標記為刪除。該文件依然能匹配查詢,但是會在 結果中被過濾掉。當段合併時,在.del 檔案中被標記為刪除的文件將不會被寫入 新段。
  3. 在新的文件被建立時,Elasticsearch 會為該文件指定一個版本號,當執行更新 時,舊版本的文件在.del 檔案中被標記為刪除,新版本的文件被索引到一個新段。

舊版本的文件依然能匹配查詢,但是會在結果中被過濾掉。

10. Elasticsearch 對於大資料量(上億量級)的聚合如何實現?

這道題目較難,相信大家看到很多類似這種回答

Elasticsearch 提供的首個近似聚合是cardinality 度量。它提供一個欄位的基數,即該欄位的distinct或者unique值的數目。它是基於HLL演算法的。HLL 會先對我們的輸入作雜湊運算,然後根據雜湊運算的結果中的 bits 做概率估算從而得到基數。其特點是:可配置的精度,用來控制記憶體的使用(更精確 = 更多記憶體);小的資料集精度是非常高的;我們可以通過配置引數,來設定去重需要的固定記憶體使用量。無論數千還是數十億的唯一值,記憶體使用量只與你配置的精確度相關。

科普&拓展

HyperLogLog:
下面簡稱為HLL,它是 LogLog 演算法的升級版,作用是能夠提供不精確的去重計數。存在以下的特點:
1. 能夠使用極少的記憶體來統計巨量的資料,在 Redis 中實現的 HyperLogLog,只需要12K記憶體就能統計2^64個數據。
2. 計數存在一定的誤差,誤差率整體較低。標準誤差為 0.81% 。
3. 誤差可以被設定輔助計算因子進行降低。
---
應用場景:
1. 基數不大,資料量不大就用不上,會有點大材小用浪費空間
2. 有侷限性,就是隻能統計基數數量,而沒辦法去知道具體的內容是什麼
3. 和bitmap相比,屬於兩種特定統計情況,簡單來說,HyperLogLog 去重比 bitmap 方便很多
4. 一般可以bitmap和hyperloglog配合使用,bitmap標識哪些使用者活躍,hyperloglog計數
---
應用場景:
1. 基數不大,資料量不大就用不上,會有點大材小用浪費空間
2. 有侷限性,就是隻能統計基數數量,而沒辦法去知道具體的內容是什麼
3. 和bitmap相比,屬於兩種特定統計情況,簡單來說,HyperLogLog 去重比 bitmap 方便很多
4. 一般可以bitmap和hyperloglog配合使用,bitmap標識哪些使用者活躍,hyperloglog計數
來源:刷刷面試

11. 在併發情況下,Elasticsearch 如果保證讀寫一致?

首先要了解什麼是一致性,在分散式系統中,我們一般通過CPA理論分析。

分散式系統不可能同時滿足一致性(C:Consistency)、可用性(A:Availability)和分割槽容忍性(P:Partition Tolerance),最多隻能同時滿足其中兩項。

  1. 可以通過版本號使用樂觀併發控制,以確保新版本不會被舊版本覆蓋,由應用層來處理具體的衝突;
  2. 另外對於寫操作,一致性級別支援 quorum/one/all,預設為 quorum,即只有當大多數分片可用時才允許寫操作。但即使大多數可用,也可能存在因為網路等原因導致寫入副本失敗,這樣該副本被認為故障,分片將會在一個不同的節點上重建。
  3. 對於讀操作,可以設定 replication 為 sync(預設),這使得操作在主分片和副本分片都完成後才會返回;如果設定 replication 為 async 時,也可以通過設定搜尋請求引數_preference 為 primary 來查詢主分片,確保文件是最新版本。

12. 介紹一下你們的個性化搜尋方案?

如果你沒有很多實戰經驗,可以基於 word2vec 做一些練習,我的部落格提供了 word2vec Java版的一些Demo。

基於 word2vec 和 Elasticsearch 實現個性化搜尋,它有以下優點:

  1. 基於word2vec的商品向量還有一個可用之處,就是可以用來實現相似商品的推薦;

推薦閱讀:

【Java併發面試】10道不得不會的Java併發基礎面試題
https://blog.csdn.net/qq_40374604/article/details/122159231

【Java基礎面試】10道不得不會的Java基礎面試題
https://blog.csdn.net/qq_40374604/article/details/122011870

【MySQL面試】10道不得不會的MySQL基礎面試題
https://javapub.blog.csdn.net/article/details/122087243

【ElasticSearch面試】10道不得不會的ElasticSearch面試題
https://javapub.blog.csdn.net/article/details/123761794