2019年常見Elasticsearch 面試題答案詳細解析(下)

程式設計師追風發表於2019-12-26

前言

1.Elasticsearch 是一個分散式的 RESTful 風格的搜尋和資料分析引擎。

(1)查詢 : Elasticsearch 允許執行和合並多種型別的搜尋 — 結構化、非結構化、地理位置、度量指標 — 搜尋方式隨心而變。
(2)分析 : 找到與查詢最匹配的十個文件是一回事。但是如果面對的是十億行日誌,又該如何解讀呢?Elasticsearch 聚合讓您能夠從大處著眼,探索資料的趨勢和模式。
(3)速度 : Elasticsearch 很快。真的,真的很快。
(4)可擴充套件性 : 可以在膝上型電腦上執行。 也可以在承載了 PB 級資料的成百上千臺伺服器上執行。
(5)彈性 : Elasticsearch 執行在一個分散式的環境中,從設計之初就考慮到了這一點。
(6)靈活性 : 具備多個案例場景。數字、文字、地理位置、結構化、非結構化。所有的資料型別都歡迎。
(7)HADOOP & SPARK : Elasticsearch + Hadoop

2.Elasticsearch是一個高度可伸縮的開源全文搜尋和分析引擎。它允許您快速和接近實時地儲存、搜尋和分析大量資料。

這裡有一些使用Elasticsearch的用例:
(1)你經營一個網上商店,你允許你的顧客搜尋你賣的產品。在這種情況下,您可以使用Elasticsearch來儲存整個產品目錄和庫存,併為它們提供搜尋和自動完成建議。
(2)你希望收集日誌或事務資料,並希望分析和挖掘這些資料,以查詢趨勢、統計、彙總或異常。在這種情況下,你可以使用loghide (Elasticsearch/ loghide /Kibana堆疊的一部分)來收集、聚合和解析資料,然後讓loghide將這些資料輸入到Elasticsearch中。一旦資料在Elasticsearch中,你就可以執行搜尋和聚合來挖掘你感興趣的任何資訊。
(3)你執行一個價格警報平臺,允許精通價格的客戶指定如下規則:“我有興趣購買特定的電子裝置,如果下個月任何供應商的產品價格低於X美元,我希望得到通知”。在這種情況下,你可以抓取供應商的價格,將它們推入到Elasticsearch中,並使用其反向搜尋(Percolator)功能來匹配價格走勢與客戶查詢,並最終在找到匹配後將警報推送給客戶。
(4)你有分析/業務智慧需求,並希望快速調查、分析、視覺化,並對大量資料提出特別問題(想想數百萬或數十億的記錄)。在這種情況下,你可以使用Elasticsearch來儲存資料,然後使用Kibana (Elasticsearch/ loghide /Kibana堆疊的一部分)來構建自定義儀表板,以視覺化對您來說很重要的資料的各個方面。此外,還可以使用Elasticsearch聚合功能對資料執行復雜的業務智慧查詢。
2019年常見Elasticsearch 面試題答案詳細解析(下)

Elasticsearch面試題

1、詳細描述一下 Elasticsearch 更新和刪除文件的過程。
2、詳細描述一下 Elasticsearch 搜尋的過程。
3、在 Elasticsearch 中,是怎麼根據一個詞找到對應的倒排索引的?
4、Elasticsearch 在部署時,對 Linux 的設定有哪些優化方法?
5、對於 GC 方面,在使用 Elasticsearch 時要注意什麼?
6、Elasticsearch 對於大資料量(上億量級)的聚合如何實現?
7、在併發情況下,Elasticsearch 如果保證讀寫一致?
8、如何監控 Elasticsearch 叢集狀態?
9、介紹下你們電商搜尋的整體技術架構。
10、介紹一下你們的個性化搜尋方案?
11、是否瞭解字典樹?
12、拼寫糾錯是如何實現的?
2019年常見Elasticsearch 面試題答案詳細解析(下)

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

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

2、詳細描述一下 Elasticsearch 搜尋的過程。

(1)搜尋被執行成一個兩階段過程,我們稱之為 Query Then Fetch;
(2)在初始查詢階段時,查詢會廣播到索引中每一個分片拷貝(主分片或者副本分片)。 每個分片在本地執行搜尋並構建一個匹配文件的大小為 from + size 的優先佇列。
PS:在搜尋的時候是會查詢 Filesystem Cache 的,但是有部分資料還在 MemoryBuffer,所以搜尋是近實時的。
(3)每個分片返回各自優先佇列中 所有文件的 ID 和排序值 給協調節點,它合併這些值到自己的優先佇列中來產生一個全域性排序後的結果列表。
(4)接下來就是 取回階段,協調節點辨別出哪些文件需要被取回並向相關的分片提交多個 GET 請求。每個分片載入並 豐 富 文件,如果有需要的話,接著返回文件給協調節點。一旦所有的文件都被取回了,協調節點返回結果給客戶端。
(5)補充:Query Then Fetch 的搜尋型別在文件相關性打分的時候參考的是本分片的資料,這樣在文件數量較少的時候可能不夠準確,DFS Query Then Fetch 增加了一個預查詢的處理,詢問 Term 和 Document frequency,這個評分更準確,但是效能會變差。*
2019年常見Elasticsearch 面試題答案詳細解析(下)

3、在 Elasticsearch 中,是怎麼根據一個詞找到對應的倒排索引的?

(1)Lucene的索引過程,就是按照全文檢索的基本過程,將倒排表寫成此檔案格式的過程。
(2)Lucene的搜尋過程,就是按照此檔案格式將索引進去的資訊讀出來,然後計算每篇文件打分(score)的過程。

4、Elasticsearch 在部署時,對 Linux 的設定有哪些優化方法?

(1)64 GB 記憶體的機器是非常理想的, 但是 32 GB 和 16 GB 機器也是很常見的。少於 8 GB 會適得其反。
(2)如果你要在更快的 CPUs 和更多的核心之間選擇,選擇更多的核心更好。多個核心提供的額外併發遠勝過稍微快一點點的時脈頻率。
(3)如果你負擔得起 SSD,它將遠遠超出任何旋轉介質。 基於 SSD 的節點,查詢和索引效能都有提升。如果你負擔得起,SSD 是一個好的選擇。
(4)即使資料中心們近在咫尺,也要避免叢集跨越多個資料中心。絕對要避免叢集跨越大的地理距離。
(5)請確保執行你應用程式的 JVM 和伺服器的 JVM 是完全一樣的。 在Elasticsearch 的幾個地方,使用 Java 的本地序列化。
(6)通過設定 gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time 可以在叢集重啟的時候避免過多的分片交換,這可能會讓資料恢復從數個小時縮短為幾秒鐘。
(7)Elasticsearch 預設被配置為使用單播發現,以防止節點無意中加入叢集。只有在同一臺機器上執行的節點才會自動組成叢集。最好使用單播代替組播。
(8)不要隨意修改垃圾回收器(CMS)和各個執行緒池的大小。
(9)把你的記憶體的(少於)一半給 Lucene(但不要超過 32 GB!),通過ES_HEAP_SIZE 環境變數設定。
(10)記憶體交換到磁碟對伺服器效能來說是致命的。如果記憶體交換到磁碟上,一個100 微秒的操作可能變成 10 毫秒。 再想想那麼多 10 微秒的操作時延累加起來。 不難看出 swapping 對於效能是多麼可怕。
(11)Lucene 使用了大 量 的檔案。同時,Elasticsearch 在節點和 HTTP 客戶端之間進行通訊也使用了大量的套接字。 所有這一切都需要足夠的檔案描述符。你應該增加你的檔案描述符,設定一個很大的值,如 64,000。
補充:索引階段效能提升方法
(1)使用批量請求並調整其大小:每次批量資料 5–15 MB 大是個不錯的起始點。
(2)儲存:使用 SSD
(3)段和合並:Elasticsearch 預設值是 20 MB/s,對機械磁碟應該是個不錯的設定。如果你用的是 SSD,可以考慮提高到 100–200 MB/s。如果你在做批量匯入,完全不在意搜尋,你可以徹底關掉合併限流。另外還可以增加index.translog.flush_threshold_size 設定,從預設的 512 MB 到更大一些的值,比如 1 GB,這可以在一次清空觸發的時候在事務日誌裡積累出更大的段。
(4)如果你的搜尋結果不需要近實時的準確度,考慮把每個索引的index.refresh_interval 改到 30s。
(5)如果你在做大批量匯入,考慮通過設定 index.number_of_replicas: 0 關閉副本。

5、對於 GC 方面,在使用 Elasticsearch 時要注意什麼?

(1)倒排詞典的索引需要常駐記憶體,無法 GC,需要監控 data node 上 segmentmemory 增長趨勢。
(2)各類快取,field cache, filter cache, indexing cache, bulk queue 等等,要設定合理的大小,並且要應該根據最壞的情況來看 heap 是否夠用,也就是各類快取全部佔滿的時候,還有 heap 空間可以分配給其他任務嗎?避免採用 clear cache等“自欺欺人”的方式來釋放記憶體。
(3)避免返回大量結果集的搜尋與聚合。確實需要大量拉取資料的場景,可以採用scan & scroll api 來實現。
(4)cluster stats 駐留記憶體並無法水平擴充套件,超大規模叢集可以考慮分拆成多個叢集通過 tribe node 連線。
(5)想知道 heap 夠不夠,必須結合實際應用場景,並對叢集的 heap 使用情況做持續的監控。
(6)根據監控資料理解記憶體需求,合理配置各類circuit breaker,將記憶體溢位風險降低到最低
2019年常見Elasticsearch 面試題答案詳細解析(下)

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

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

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

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

8、如何監控 Elasticsearch 叢集狀態?

Marvel 讓你可以很簡單的通過 Kibana 監控 Elasticsearch。你可以實時檢視你的叢集健康狀態和效能,也可以分析過去的叢集、索引和節點指標。

9、介紹下你們電商搜尋的整體技術架構。

2019年常見Elasticsearch 面試題答案詳細解析(下)

10、介紹一下你們的個性化搜尋方案?

基於word2vec和Elasticsearch實現個性化搜尋
(1)基於word2vec、Elasticsearch和自定義的指令碼外掛,我們就實現了一個個性化的搜尋服務,相對於原有的實現,新版的點選率和轉化率都有大幅的提升;
(2)基於word2vec的商品向量還有一個可用之處,就是可以用來實現相似商品的推薦;
(3)使用word2vec來實現個性化搜尋或個性化推薦是有一定侷限性的,因為它只能處理使用者點選歷史這樣的時序資料,而無法全面的去考慮使用者偏好,這個還是有很大的改進和提升的空間;

11、是否瞭解字典樹?

常用字典資料結構如下所示:
2019年常見Elasticsearch 面試題答案詳細解析(下)
Trie 的核心思想是空間換時間,利用字串的公共字首來降低查詢時間的開銷以達到提高效率的目的。它有 3 個基本性質:
1)根節點不包含字元,除根節點外每一個節點都只包含一個字元。
2)從根節點到某一節點,路徑上經過的字元連線起來,為該節點對應的字串。
3)每個節點的所有子節點包含的字元都不相同。
2019年常見Elasticsearch 面試題答案詳細解析(下)
(1)可以看到,trie 樹每一層的節點數是 26^i 級別的。所以為了節省空間,我們還可以用動態連結串列,或者用陣列來模擬動態。而空間的花費,不會超過單詞數×單詞長度。
(2)實現:對每個結點開一個字母集大小的陣列,每個結點掛一個連結串列,使用左兒子右兄弟表示法記錄這棵樹;
(3)對於中文的字典樹,每個節點的子節點用一個雜湊表儲存,這樣就不用浪費太大的空間,而且查詢速度上可以保留雜湊的複雜度 O(1)。

12、拼寫糾錯是如何實現的?

(1)拼寫糾錯是基於編輯距離來實現;編輯距離是一種標準的方法,它用來表示經過插入、刪除和替換操作從一個字串轉換到另外一個字串的最小操作步數;
(2)編輯距離的計算過程:比如要計算 batyu 和 beauty 的編輯距離,先建立一個7×8 的表(batyu 長度為 5,coffee 長度為 6,各加 2),接著,在如下位置填入黑色數字。其他格的計算過程是取以下三個值的最小值:
如果最上方的字元等於最左方的字元,則為左上方的數字。否則為左上方的數字+1。(對於 3,3 來說為 0)
左方數字+1(對於 3,3 格來說為 2)
上方數字+1(對於 3,3 格來說為 2)
最終取右下角的值即為編輯距離的值 3。
2019年常見Elasticsearch 面試題答案詳細解析(下)

對於拼寫糾錯,我們考慮構造一個度量空間(Metric Space),該空間內任何關係滿足以下三條基本條件:
d(x,y) = 0 -- 假如 x 與 y 的距離為 0,則 x=y
d(x,y) = d(y,x) -- x 到 y 的距離等同於 y 到 x 的距離
d(x,y) + d(y,z) >= d(x,z) -- 三角不等式
(1)根據三角不等式,則滿足與 query 距離在 n 範圍內的另一個字元轉 B,其與 A的距離最大為 d+n,最小為 d-n。
(2)BK 樹的構造就過程如下:每個節點有任意個子節點,每條邊有個值表示編輯距離。所有子節點到父節點的邊上標註 n 表示編輯距離恰好為 n。比如,我們有棵樹父節點是”book”和兩個子節點”cake”和”books”,”book”到”books”的邊標號 1,”book”到”cake”的邊上標號 4。從字典裡構造好樹後,無論何時你想插入新單詞時,計算該單詞與根節點的編輯距離,並且查詢數值為d(neweord, root)的邊。遞迴得與各子節點進行比較,直到沒有子節點,你就可以建立新的子節點並將新單詞儲存在那。比如,插入”boo”到剛才上述例子的樹中,我們先檢查根節點,查詢 d(“book”, “boo”) = 1 的邊,然後檢查標號為1 的邊的子節點,得到單詞”books”。我們再計算距離 d(“books”, “boo”)=2,則將新單詞插在”books”之後,邊標號為 2。
3、查詢相似詞如下:計算單詞與根節點的編輯距離 d,然後遞迴查詢每個子節點標號為 d-n 到 d+n(包含)的邊。假如被檢查的節點與搜尋單詞的距離 d 小於 n,則返回該節點並繼續查詢。比如輸入 cape 且最大容忍距離為 1,則先計算和根的編輯距離 d(“book”, “cape”)=4,然後接著找和根節點之間編輯距離為 3 到5 的,這個就找到了 cake 這個節點,計算 d(“cake”, “cape”)=1,滿足條件所以返回 cake,然後再找和 cake 節點編輯距離是 0 到 2 的,分別找到 cape 和cart 節點,這樣就得到 cape 這個滿足條件的結果。
2019年常見Elasticsearch 面試題答案詳細解析(下)


最後

歡迎大家關注我的公眾號【程式設計師追風】,2019年多家公司java面試題整理了1000多道400多頁pdf文件,文章都會在裡面更新,整理的資料也會放在裡面。

喜歡文章記得關注我點個贊喲,感謝支援!


相關文章