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

前言

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聚合功能對數據執行復雜的業務智能查詢。

Elasticsearch面試題

一、詳細描述一下 Elasticsearch 更新和刪除文檔的過程。
二、詳細描述一下 Elasticsearch 搜索的過程。
三、在 Elasticsearch 中,是怎麼根據一個詞找到對應的倒排索引的?
四、Elasticsearch 在部署時,對 Linux 的設置有哪些優化方法?
五、對於 GC 方面,在使用 Elasticsearch 時要注意什麼?
六、Elasticsearch 對於大數據量(上億量級)的聚合如何實現?
七、在併發狀況下,Elasticsearch 若是保證讀寫一致?
八、如何監控 Elasticsearch 集羣狀態?
九、介紹下大家電商搜索的總體技術架構。
十、介紹一下大家的個性化搜索方案?
十一、是否瞭解字典樹?
十二、拼寫糾錯是如何實現的?

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

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

二、詳細描述一下 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,這個評分更準確,可是性能會變差。*

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

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

四、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 關閉副本。

五、對於 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,將內存溢出風險下降到最低

六、Elasticsearch 對於大數據量(上億量級)的聚合如何實現?

Elasticsearch 提供的首個近似聚合是 cardinality 度量。它提供一個字段的基數,即該字段的 distinct 或者 unique 值的數目。它是基於 HLL 算法的。HLL 會先對咱們的輸入做哈希運算,而後根據哈希運算的結果中的 bits 作機率估算從而獲得基數。其特色是:可配置的精度,用來控制內存的使用(更精確 = 更多內存);小的數據集精度是很是高的;咱們能夠經過配置參數,來設置去重須要的固定內存使用量。不管數千仍是數十億的惟一值,內存使用量只與你配置的精確度相關。

七、在併發狀況下,Elasticsearch 若是保證讀寫一致?

(1)能夠經過版本號使用樂觀併發控制,以確保新版本不會被舊版本覆蓋,由應用層來處理具體的衝突;
(2)另外對於寫操做,一致性級別支持 quorum/one/all,默認爲 quorum,即只有當大多數分片可用時才容許寫操做。但即便大多數可用,也可能存在由於網絡等緣由致使寫入副本失敗,這樣該副本被認爲故障,分片將會在一個不一樣的節點上重建。
(3)對於讀操做,能夠設置 replication 爲 sync(默認),這使得操做在主分片和副本分片都完成後纔會返回;若是設置 replication 爲 async 時,也能夠經過設置搜索請求參數_preference 爲 primary 來查詢主分片,確保文檔是最新版本。

八、如何監控 Elasticsearch 集羣狀態?

Marvel 讓你能夠很簡單的經過 Kibana 監控 Elasticsearch。你能夠實時查看你的集羣健康狀態和性能,也能夠分析過去的集羣、索引和節點指標。

九、介紹下大家電商搜索的總體技術架構。

十、介紹一下大家的個性化搜索方案?

基於word2vec和Elasticsearch實現個性化搜索
(1)基於word2vec、Elasticsearch和自定義的腳本插件,咱們就實現了一個個性化的搜索服務,相對於原有的實現,新版的點擊率和轉化率都有大幅的提高;
(2)基於word2vec的商品向量還有一個可用之處,就是能夠用來實現類似商品的推薦;
(3)使用word2vec來實現個性化搜索或個性化推薦是有必定侷限性的,由於它只能處理用戶點擊歷史這樣的時序數據,而沒法全面的去考慮用戶偏好,這個仍是有很大的改進和提高的空間;

十一、是否瞭解字典樹?

經常使用字典數據結構以下所示:
Trie 的核心思想是空間換時間,利用字符串的公共前綴來下降查詢時間的開銷以達到提升效率的目的。它有 3 個基本性質:
1)根節點不包含字符,除根節點外每個節點都只包含一個字符。
2)從根節點到某一節點,路徑上通過的字符鏈接起來,爲該節點對應的字符串。
3)每一個節點的全部子節點包含的字符都不相同。
(1)能夠看到,trie 樹每一層的節點數是 26^i 級別的。因此爲了節省空間,咱們還能夠用動態鏈表,或者用數組來模擬動態。而空間的花費,不會超過單詞數×單詞長度。
(2)實現:對每一個結點開一個字母集大小的數組,每一個結點掛一個鏈表,使用左兒子右兄弟表示法記錄這棵樹;
(3)對於中文的字典樹,每一個節點的子節點用一個哈希表存儲,這樣就不用浪費太大的空間,並且查詢速度上能夠保留哈希的複雜度 O(1)。

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

(1)拼寫糾錯是基於編輯距離來實現;編輯距離是一種標準的方法,它用來表示通過插入、刪除和替換操做從一個字符串轉換到另一個字符串的最小操做步數;
(2)編輯距離的計算過程:好比要計算 batyu 和 beauty 的編輯距離,先建立一個7×8 的表(batyu 長度爲 5,coffee 長度爲 6,各加 2),接着,在以下位置填入黑色數字。其餘格的計算過程是取如下三個值的最小值:
若是最上方的字符等於最左方的字符,則爲左上方的數字。不然爲左上方的數字+1。(對於 3,3 來講爲 0)
左方數字+1(對於 3,3 格來講爲 2)
上方數字+1(對於 3,3 格來講爲 2)
最終取右下角的值即爲編輯距離的值 3。

對於拼寫糾錯,咱們考慮構造一個度量空間(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。
三、查詢類似詞以下:計算單詞與根節點的編輯距離 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年多家公司java面試題整理了1000多道400多頁pdf文檔,文章都會在裏面更新,整理的資料也會放在裏面。
java

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

相關文章
相關標籤/搜索