1W字解析常見(jiàn)ES面試題(建議收藏)
前言
1.Elasticsearch 是一個(gè)分布式的 RESTful 風(fēng)格的搜索和數(shù)據(jù)分析引擎。
(1)查詢(xún) :Elasticsearch 允許執(zhí)行和合并多種類(lèi)型的搜索 — 結(jié)構(gòu)化、非結(jié)構(gòu)化、地理位置、度量指標(biāo) — 搜索方式隨心而變。
(2)分析 :找到與查詢(xún)最匹配的十個(gè)文檔是一回事。但是如果面對(duì)的是十億行日志,又該如何解讀呢?Elasticsearch 聚合讓您能夠從大處著眼,探索數(shù)據(jù)的趨勢(shì)和模式。
(3)速度 :Elasticsearch 很快。真的,真的很快。
(4)可擴(kuò)展性 :可以在筆記本電腦上運(yùn)行。也可以在承載了 PB 級(jí)數(shù)據(jù)的成百上千臺(tái)服務(wù)器上運(yùn)行。
(5)彈性 :Elasticsearch 運(yùn)行在一個(gè)分布式的環(huán)境中,從設(shè)計(jì)之初就考慮到了這一點(diǎn)。
(6)靈活性 :具備多個(gè)案例場(chǎng)景。數(shù)字、文本、地理位置、結(jié)構(gòu)化、非結(jié)構(gòu)化。所有的數(shù)據(jù)類(lèi)型都?xì)g迎。
(7)HADOOP & SPARK :Elasticsearch + Hadoop
2.Elasticsearch是一個(gè)高度可伸縮的開(kāi)源全文搜索和分析引擎。它允許您快速和接近實(shí)時(shí)地存儲(chǔ)、搜索和分析大量數(shù)據(jù)。
這里有一些使用Elasticsearch的用例:
(1)你經(jīng)營(yíng)一個(gè)網(wǎng)上商店,你允許你的顧客搜索你賣(mài)的產(chǎn)品。在這種情況下,您可以使用Elasticsearch來(lái)存儲(chǔ)整個(gè)產(chǎn)品目錄和庫(kù)存,并為它們提供搜索和自動(dòng)完成建議。
(2)你希望收集日志或事務(wù)數(shù)據(jù),并希望分析和挖掘這些數(shù)據(jù),以查找趨勢(shì)、統(tǒng)計(jì)、匯總或異常。在這種情況下,你可以使用loghide (Elasticsearch/ loghide /Kibana堆棧的一部分)來(lái)收集、聚合和解析數(shù)據(jù),然后讓loghide將這些數(shù)據(jù)輸入到Elasticsearch中。一旦數(shù)據(jù)在Elasticsearch中,你就可以運(yùn)行搜索和聚合來(lái)挖掘你感興趣的任何信息。
(3)你運(yùn)行一個(gè)價(jià)格警報(bào)平臺(tái),允許精通價(jià)格的客戶(hù)指定如下規(guī)則:“我有興趣購(gòu)買(mǎi)特定的電子設(shè)備,如果下個(gè)月任何供應(yīng)商的產(chǎn)品價(jià)格低于X美元,我希望得到通知”。在這種情況下,你可以抓取供應(yīng)商的價(jià)格,將它們推入到Elasticsearch中,并使用其反向搜索(Percolator)功能來(lái)匹配價(jià)格走勢(shì)與客戶(hù)查詢(xún),并最終在找到匹配后將警報(bào)推送給客戶(hù)。
(4)你有分析/業(yè)務(wù)智能需求,并希望快速調(diào)查、分析、可視化,并對(duì)大量數(shù)據(jù)提出特別問(wèn)題(想想數(shù)百萬(wàn)或數(shù)十億的記錄)。在這種情況下,你可以使用Elasticsearch來(lái)存儲(chǔ)數(shù)據(jù),然后使用Kibana (Elasticsearch/ loghide /Kibana堆棧的一部分)來(lái)構(gòu)建自定義儀表板,以可視化對(duì)您來(lái)說(shuō)很重要的數(shù)據(jù)的各個(gè)方面。此外,還可以使用Elasticsearch聚合功能對(duì)數(shù)據(jù)執(zhí)行復(fù)雜的業(yè)務(wù)智能查詢(xún)。
Elasticsearch 面試題
1、elasticsearch 了解多少,說(shuō)說(shuō)你們公司 es 的集群架構(gòu),索引數(shù)據(jù)大小,分片有多少,以及一些調(diào)優(yōu)手段 。
2、elasticsearch 的倒排索引是什么
3、elasticsearch 索引數(shù)據(jù)多了怎么辦,如何調(diào)優(yōu),部署
4、elasticsearch 是如何實(shí)現(xiàn) master 選舉的
5、詳細(xì)描述一下 Elasticsearch 索引文檔的過(guò)程
6、詳細(xì)描述一下 Elasticsearch 搜索的過(guò)程?
7、Elasticsearch 在部署時(shí),對(duì) Linux 的設(shè)置有哪些優(yōu)化方法
8、lucence 內(nèi)部結(jié)構(gòu)是什么?
9、Elasticsearch 是如何實(shí)現(xiàn) Master 選舉的?
10、Elasticsearch 中的節(jié)點(diǎn)(比如共 20 個(gè)),其中的 10 個(gè)選了一個(gè)master,另外 10 個(gè)選了另一個(gè) master,怎么辦?
11、客戶(hù)端在和集群連接時(shí),如何選擇特定的節(jié)點(diǎn)執(zhí)行請(qǐng)求的?
12、詳細(xì)描述一下 Elasticsearch 索引文檔的過(guò)程。
13、詳細(xì)描述一下 Elasticsearch 更新和刪除文檔的過(guò)程。
14、詳細(xì)描述一下 Elasticsearch 搜索的過(guò)程。
15、在 Elasticsearch 中,是怎么根據(jù)一個(gè)詞找到對(duì)應(yīng)的倒排索引的?
16、Elasticsearch 在部署時(shí),對(duì) Linux 的設(shè)置有哪些優(yōu)化方法?
17、對(duì)于 GC 方面,在使用 Elasticsearch 時(shí)要注意什么?
18、Elasticsearch 對(duì)于大數(shù)據(jù)量(上億量級(jí))的聚合如何實(shí)現(xiàn)?
19、在并發(fā)情況下,Elasticsearch 如果保證讀寫(xiě)一致?
20、如何監(jiān)控 Elasticsearch 集群狀態(tài)?
21、介紹下你們電商搜索的整體技術(shù)架構(gòu)。
22、介紹一下你們的個(gè)性化搜索方案?
23、是否了解字典樹(shù)?
24、拼寫(xiě)糾錯(cuò)是如何實(shí)現(xiàn)的?
1、elasticsearch 了解多少,說(shuō)說(shuō)你們公司 es 的集群架構(gòu),索引數(shù)據(jù)大小,分片有多少,以及一些調(diào)優(yōu)手段 。
面試官:想了解應(yīng)聘者之前公司接觸的 ES 使用場(chǎng)景、規(guī)模,有沒(méi)有做過(guò)比較大規(guī)模的索引設(shè)計(jì)、規(guī)劃、調(diào)優(yōu)。
解答:如實(shí)結(jié)合自己的實(shí)踐場(chǎng)景回答即可。
比如:ES 集群架構(gòu) 13 個(gè)節(jié)點(diǎn),索引根據(jù)通道不同共 20+索引,根據(jù)日期,每日遞增 20+,索引:10 分片,每日遞增 1 億+數(shù)據(jù),每個(gè)通道每天索引大小控制:150GB 之內(nèi)。
僅索引層面調(diào)優(yōu)手段:
1.1、設(shè)計(jì)階段調(diào)優(yōu)
(1)根據(jù)業(yè)務(wù)增量需求,采取基于日期模板創(chuàng)建索引,通過(guò) roll over API 滾動(dòng)索引;
(2)使用別名進(jìn)行索引管理;
(3)每天凌晨定時(shí)對(duì)索引做 force_merge 操作,以釋放空間;
(4)采取冷熱分離機(jī)制,熱數(shù)據(jù)存儲(chǔ)到 SSD,提高檢索效率;冷數(shù)據(jù)定期進(jìn)行 shrink操作,以縮減存儲(chǔ);
(5)采取 curator 進(jìn)行索引的生命周期管理;
(6)僅針對(duì)需要分詞的字段,合理的設(shè)置分詞器;
(7)Mapping 階段充分結(jié)合各個(gè)字段的屬性,是否需要檢索、是否需要存儲(chǔ)等。……..
1.2、寫(xiě)入調(diào)優(yōu)
(1)寫(xiě)入前副本數(shù)設(shè)置為 0;
(2)寫(xiě)入前關(guān)閉 refresh_interval 設(shè)置為-1,禁用刷新機(jī)制;
(3)寫(xiě)入過(guò)程中:采取 bulk 批量寫(xiě)入;
(4)寫(xiě)入后恢復(fù)副本數(shù)和刷新間隔;
(5)盡量使用自動(dòng)生成的 id。
1.3、查詢(xún)調(diào)優(yōu)
(1)禁用 wildcard;
(2)禁用批量 terms(成百上千的場(chǎng)景);
(3)充分利用倒排索引機(jī)制,能 keyword 類(lèi)型盡量 keyword;
(4)數(shù)據(jù)量大時(shí)候,可以先基于時(shí)間敲定索引再檢索;
(5)設(shè)置合理的路由機(jī)制。
1.4、其他調(diào)優(yōu)
部署調(diào)優(yōu),業(yè)務(wù)調(diào)優(yōu)等。
上面的提及一部分,面試者就基本對(duì)你之前的實(shí)踐或者運(yùn)維經(jīng)驗(yàn)有所評(píng)估了。
2、elasticsearch 的倒排索引是什么
面試官:想了解你對(duì)基礎(chǔ)概念的認(rèn)知。
解答:通俗解釋一下就可以。
傳統(tǒng)的我們的檢索是通過(guò)文章,逐個(gè)遍歷找到對(duì)應(yīng)關(guān)鍵詞的位置。
而倒排索引,是通過(guò)分詞策略,形成了詞和文章的映射關(guān)系表,這種詞典+映射表即為倒排索引。有了倒排索引,就能實(shí)現(xiàn) o(1)時(shí)間復(fù)雜度的效率檢索文章了,極大的提高了檢索效率。

學(xué)術(shù)的解答方式:
倒排索引,相反于一篇文章包含了哪些詞,它從詞出發(fā),記載了這個(gè)詞在哪些文檔中出現(xiàn)過(guò),由兩部分組成——詞典和倒排表。
加分項(xiàng):倒排索引的底層實(shí)現(xiàn)是基于:FST(Finite State Transducer)數(shù)據(jù)結(jié)構(gòu)。
lucene 從 4+版本后開(kāi)始大量使用的數(shù)據(jù)結(jié)構(gòu)是 FST。FST 有兩個(gè)優(yōu)點(diǎn):
(1)空間占用小。通過(guò)對(duì)詞典中單詞前綴和后綴的重復(fù)利用,壓縮了存儲(chǔ)空間;
(2)查詢(xún)速度快。O(len(str))的查詢(xún)時(shí)間復(fù)雜度。
3、elasticsearch 索引數(shù)據(jù)多了怎么辦,如何調(diào)優(yōu),部署
面試官:想了解大數(shù)據(jù)量的運(yùn)維能力。
解答:索引數(shù)據(jù)的規(guī)劃,應(yīng)在前期做好規(guī)劃,正所謂“設(shè)計(jì)先行,編碼在后”,這樣才能有效的避免突如其來(lái)的數(shù)據(jù)激增導(dǎo)致集群處理能力不足引發(fā)的線(xiàn)上客戶(hù)檢索或者其他業(yè)務(wù)受到影響。
如何調(diào)優(yōu),正如問(wèn)題 1 所說(shuō),這里細(xì)化一下:
3.1 動(dòng)態(tài)索引層面
基于模板+時(shí)間+rollover api 滾動(dòng)創(chuàng)建索引,舉例:設(shè)計(jì)階段定義:blog 索引的模板格式為:blog_index_時(shí)間戳的形式,每天遞增數(shù)據(jù)。這樣做的好處:不至于數(shù)據(jù)量激增導(dǎo)致單個(gè)索引數(shù)據(jù)量非常大,接近于上線(xiàn) 2 的32 次冪-1,索引存儲(chǔ)達(dá)到了 TB+甚至更大。
一旦單個(gè)索引很大,存儲(chǔ)等各種風(fēng)險(xiǎn)也隨之而來(lái),所以要提前考慮+及早避免。
3.2 存儲(chǔ)層面
冷熱數(shù)據(jù)分離存儲(chǔ),熱數(shù)據(jù)(比如最近 3 天或者一周的數(shù)據(jù)),其余為冷數(shù)據(jù)。
對(duì)于冷數(shù)據(jù)不會(huì)再寫(xiě)入新數(shù)據(jù),可以考慮定期 force_merge 加 shrink 壓縮操作,節(jié)省存儲(chǔ)空間和檢索效率。
3.3 部署層面
一旦之前沒(méi)有規(guī)劃,這里就屬于應(yīng)急策略。
結(jié)合 ES 自身的支持動(dòng)態(tài)擴(kuò)展的特點(diǎn),動(dòng)態(tài)新增機(jī)器的方式可以緩解集群壓力,注意:如果之前主節(jié)點(diǎn)等規(guī)劃合理,不需要重啟集群也能完成動(dòng)態(tài)新增的。
4、elasticsearch 是如何實(shí)現(xiàn) master 選舉的
面試官:想了解 ES 集群的底層原理,不再只關(guān)注業(yè)務(wù)層面了。
解答:
前置前提:
(1)只有候選主節(jié)點(diǎn)(master:true)的節(jié)點(diǎn)才能成為主節(jié)點(diǎn)。
(2)最小主節(jié)點(diǎn)數(shù)(min_master_nodes)的目的是防止腦裂。
核對(duì)了一下代碼,核心入口為 findMaster,選擇主節(jié)點(diǎn)成功返回對(duì)應(yīng) Master,否則返回 null。選舉流程大致描述如下:
第一步:確認(rèn)候選主節(jié)點(diǎn)數(shù)達(dá)標(biāo),elasticsearch.yml 設(shè)置的值
discovery.zen.minimum_master_nodes;
第二步:比較:先判定是否具備 master 資格,具備候選主節(jié)點(diǎn)資格的優(yōu)先返回;
若兩節(jié)點(diǎn)都為候選主節(jié)點(diǎn),則 id 小的值會(huì)主節(jié)點(diǎn)。注意這里的 id 為 string 類(lèi)型。
題外話(huà):獲取節(jié)點(diǎn) id 的方法。
1GET /_cat/nodes?v&h=ip,port,heapPercent,heapMax,id,name
2ip port heapPercent heapMax id name
5、詳細(xì)描述一下 Elasticsearch 索引文檔的過(guò)程
面試官:想了解 ES 的底層原理,不再只關(guān)注業(yè)務(wù)層面了。
解答:
這里的索引文檔應(yīng)該理解為文檔寫(xiě)入 ES,創(chuàng)建索引的過(guò)程。
文檔寫(xiě)入包含:?jiǎn)挝臋n寫(xiě)入和批量 bulk 寫(xiě)入,這里只解釋一下:?jiǎn)挝臋n寫(xiě)入流程。
記住官方文檔中的這個(gè)圖。

第一步:客戶(hù)寫(xiě)集群某節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),發(fā)送請(qǐng)求。(如果沒(méi)有指定路由/協(xié)調(diào)節(jié)點(diǎn),請(qǐng)求的節(jié)點(diǎn)扮演路由節(jié)點(diǎn)的角色。)
第二步:節(jié)點(diǎn) 1 接受到請(qǐng)求后,使用文檔_id 來(lái)確定文檔屬于分片 0。請(qǐng)求會(huì)被轉(zhuǎn)到另外的節(jié)點(diǎn),假定節(jié)點(diǎn) 3。因此分片 0 的主分片分配到節(jié)點(diǎn) 3 上。
第三步:節(jié)點(diǎn) 3 在主分片上執(zhí)行寫(xiě)操作,如果成功,則將請(qǐng)求并行轉(zhuǎn)發(fā)到節(jié)點(diǎn) 1和節(jié)點(diǎn) 2 的副本分片上,等待結(jié)果返回。所有的副本分片都報(bào)告成功,節(jié)點(diǎn) 3 將向協(xié)調(diào)節(jié)點(diǎn)(節(jié)點(diǎn) 1)報(bào)告成功,節(jié)點(diǎn) 1 向請(qǐng)求客戶(hù)端報(bào)告寫(xiě)入成功。
如果面試官再問(wèn):第二步中的文檔獲取分片的過(guò)程?
回答:借助路由算法獲取,路由算法就是根據(jù)路由和文檔 id 計(jì)算目標(biāo)的分片 id 的過(guò)程。
1shard = hash(_routing) % (num_of_primary_shards)
6、詳細(xì)描述一下 Elasticsearch 搜索的過(guò)程?
面試官:想了解 ES 搜索的底層原理,不再只關(guān)注業(yè)務(wù)層面了。
解答:
搜索拆解為“query then fetch” 兩個(gè)階段。
query 階段的目的:定位到位置,但不取。
步驟拆解如下:
(1)假設(shè)一個(gè)索引數(shù)據(jù)有 5 主+1 副本 共 10 分片,一次請(qǐng)求會(huì)命中(主或者副本分片中)的一個(gè)。
(2)每個(gè)分片在本地進(jìn)行查詢(xún),結(jié)果返回到本地有序的優(yōu)先隊(duì)列中。
(3)第 2)步驟的結(jié)果發(fā)送到協(xié)調(diào)節(jié)點(diǎn),協(xié)調(diào)節(jié)點(diǎn)產(chǎn)生一個(gè)全局的排序列表。
fetch 階段的目的:取數(shù)據(jù)。
路由節(jié)點(diǎn)獲取所有文檔,返回給客戶(hù)端。
7、Elasticsearch 在部署時(shí),對(duì) Linux 的設(shè)置有哪些優(yōu)化方法
面試官:想了解對(duì) ES 集群的運(yùn)維能力。
解答:
(1)關(guān)閉緩存 swap;
(2)堆內(nèi)存設(shè)置為:Min(節(jié)點(diǎn)內(nèi)存/2, 32GB);
(3)設(shè)置最大文件句柄數(shù);
(4)線(xiàn)程池+隊(duì)列大小根據(jù)業(yè)務(wù)需要做調(diào)整;
(5)磁盤(pán)存儲(chǔ) raid 方式——存儲(chǔ)有條件使用 RAID10,增加單節(jié)點(diǎn)性能以及避免單節(jié)點(diǎn)存儲(chǔ)故障。
8、lucence 內(nèi)部結(jié)構(gòu)是什么?
面試官:想了解你的知識(shí)面的廣度和深度。
解答:

Lucene 是有索引和搜索的兩個(gè)過(guò)程,包含索引創(chuàng)建,索引,搜索三個(gè)要點(diǎn)。可以基于這個(gè)脈絡(luò)展開(kāi)一些。
9、Elasticsearch 是如何實(shí)現(xiàn) Master 選舉的?
(1)Elasticsearch 的選主是 ZenDiscovery 模塊負(fù)責(zé)的,主要包含 Ping(節(jié)點(diǎn)之間通過(guò)這個(gè) RPC 來(lái)發(fā)現(xiàn)彼此)和 Unicast(單播模塊包含一個(gè)主機(jī)列表以控制哪些節(jié)點(diǎn)需要 ping 通)這兩部分;
(2)對(duì)所有可以成為 master 的節(jié)點(diǎn)(node.master: true)根據(jù) nodeId 字典排序,每次選舉每個(gè)節(jié)點(diǎn)都把自己所知道節(jié)點(diǎn)排一次序,然后選出第一個(gè)(第 0 位)節(jié)點(diǎn),暫且認(rèn)為它是 master 節(jié)點(diǎn)。
(3)如果對(duì)某個(gè)節(jié)點(diǎn)的投票數(shù)達(dá)到一定的值(可以成為 master 節(jié)點(diǎn)數(shù) n/2+1)并且該節(jié)點(diǎn)自己也選舉自己,那這個(gè)節(jié)點(diǎn)就是 master。否則重新選舉一直到滿(mǎn)足上述條件。
(4)補(bǔ)充:master 節(jié)點(diǎn)的職責(zé)主要包括集群、節(jié)點(diǎn)和索引的管理,不負(fù)責(zé)文檔級(jí)別的管理;data 節(jié)點(diǎn)可以關(guān)閉 http 功能*。
10、Elasticsearch 中的節(jié)點(diǎn)(比如共 20 個(gè)),其中的 10 個(gè)
選了一個(gè) master,另外 10 個(gè)選了另一個(gè) master,怎么辦?
(1)當(dāng)集群 master 候選數(shù)量不小于 3 個(gè)時(shí),可以通過(guò)設(shè)置最少投票通過(guò)數(shù)量(discovery.zen.minimum_master_nodes)超過(guò)所有候選節(jié)點(diǎn)一半以上來(lái)解決腦裂問(wèn)題;
(3)當(dāng)候選數(shù)量為兩個(gè)時(shí),只能修改為唯一的一個(gè) master 候選,其他作為 data節(jié)點(diǎn),避免腦裂問(wèn)題。
11、客戶(hù)端在和集群連接時(shí),如何選擇特定的節(jié)點(diǎn)執(zhí)行請(qǐng)求的?
TransportClient 利用 transport 模塊遠(yuǎn)程連接一個(gè) elasticsearch 集群。它并不加入到集群中,只是簡(jiǎn)單的獲得一個(gè)或者多個(gè)初始化的 transport 地址,并以 輪詢(xún) 的方式與這些地址進(jìn)行通信。
12、詳細(xì)描述一下 Elasticsearch 索引文檔的過(guò)程。
協(xié)調(diào)節(jié)點(diǎn)默認(rèn)使用文檔 ID 參與計(jì)算(也支持通過(guò) routing),以便為路由提供合適的分片。
shard = hash(document_id) % (num_of_primary_shards)
(1)當(dāng)分片所在的節(jié)點(diǎn)接收到來(lái)自協(xié)調(diào)節(jié)點(diǎn)的請(qǐng)求后,會(huì)將請(qǐng)求寫(xiě)入到 MemoryBuffer,然后定時(shí)(默認(rèn)是每隔 1 秒)寫(xiě)入到 Filesystem Cache,這個(gè)從 MomeryBuffer 到 Filesystem Cache 的過(guò)程就叫做 refresh;
(2)當(dāng)然在某些情況下,存在 Momery Buffer 和 Filesystem Cache 的數(shù)據(jù)可能會(huì)丟失,ES 是通過(guò) translog 的機(jī)制來(lái)保證數(shù)據(jù)的可靠性的。其實(shí)現(xiàn)機(jī)制是接收到請(qǐng)求后,同時(shí)也會(huì)寫(xiě)入到 translog 中 ,當(dāng) Filesystem cache 中的數(shù)據(jù)寫(xiě)入到磁盤(pán)中時(shí),才會(huì)清除掉,這個(gè)過(guò)程叫做 flush;
(3)在 flush 過(guò)程中,內(nèi)存中的緩沖將被清除,內(nèi)容被寫(xiě)入一個(gè)新段,段的 fsync將創(chuàng)建一個(gè)新的提交點(diǎn),并將內(nèi)容刷新到磁盤(pán),舊的 translog 將被刪除并開(kāi)始一個(gè)新的 translog。
(4)flush 觸發(fā)的時(shí)機(jī)是定時(shí)觸發(fā)(默認(rèn) 30 分鐘)或者 translog 變得太大(默認(rèn)為 512M)時(shí);

補(bǔ)充:關(guān)于 Lucene 的 Segement:
(1)Lucene 索引是由多個(gè)段組成,段本身是一個(gè)功能齊全的倒排索引。
(2)段是不可變的,允許 Lucene 將新的文檔增量地添加到索引中,而不用從頭重建索引。
(3)對(duì)于每一個(gè)搜索請(qǐng)求而言,索引中的所有段都會(huì)被搜索,并且每個(gè)段會(huì)消耗CPU 的時(shí)鐘周、文件句柄和內(nèi)存。這意味著段的數(shù)量越多,搜索性能會(huì)越低。
(4)為了解決這個(gè)問(wèn)題,Elasticsearch 會(huì)合并小段到一個(gè)較大的段,提交新的合并段到磁盤(pán),并刪除那些舊的小段。
13、詳細(xì)描述一下 Elasticsearch 更新和刪除文檔的過(guò)程。
(1)刪除和更新也都是寫(xiě)操作,但是 Elasticsearch 中的文檔是不可變的,因此不能被刪除或者改動(dòng)以展示其變更;
(2)磁盤(pán)上的每個(gè)段都有一個(gè)相應(yīng)的.del 文件。當(dāng)刪除請(qǐng)求發(fā)送后,文檔并沒(méi)有真的被刪除,而是在.del 文件中被標(biāo)記為刪除。該文檔依然能匹配查詢(xún),但是會(huì)在結(jié)果中被過(guò)濾掉。當(dāng)段合并時(shí),在.del 文件中被標(biāo)記為刪除的文檔將不會(huì)被寫(xiě)入新段。
(3)在新的文檔被創(chuàng)建時(shí),Elasticsearch 會(huì)為該文檔指定一個(gè)版本號(hào),當(dāng)執(zhí)行更新時(shí),舊版本的文檔在.del 文件中被標(biāo)記為刪除,新版本的文檔被索引到一個(gè)新段。舊版本的文檔依然能匹配查詢(xún),但是會(huì)在結(jié)果中被過(guò)濾掉。
14、詳細(xì)描述一下 Elasticsearch 搜索的過(guò)程。
(1)搜索被執(zhí)行成一個(gè)兩階段過(guò)程,我們稱(chēng)之為 Query Then Fetch;
(2)在初始查詢(xún)階段時(shí),查詢(xún)會(huì)廣播到索引中每一個(gè)分片拷貝(主分片或者副本分片)。每個(gè)分片在本地執(zhí)行搜索并構(gòu)建一個(gè)匹配文檔的大小為 from + size 的優(yōu)先隊(duì)列。
PS:在搜索的時(shí)候是會(huì)查詢(xún) Filesystem Cache 的,但是有部分?jǐn)?shù)據(jù)還在 MemoryBuffer,所以搜索是近實(shí)時(shí)的。
(3)每個(gè)分片返回各自?xún)?yōu)先隊(duì)列中 所有文檔的 ID 和排序值 給協(xié)調(diào)節(jié)點(diǎn),它合并這些值到自己的優(yōu)先隊(duì)列中來(lái)產(chǎn)生一個(gè)全局排序后的結(jié)果列表。
(4)接下來(lái)就是 取回階段,協(xié)調(diào)節(jié)點(diǎn)辨別出哪些文檔需要被取回并向相關(guān)的分片提交多個(gè) GET 請(qǐng)求。每個(gè)分片加載并 豐 富 文檔,如果有需要的話(huà),接著返回文檔給協(xié)調(diào)節(jié)點(diǎn)。一旦所有的文檔都被取回了,協(xié)調(diào)節(jié)點(diǎn)返回結(jié)果給客戶(hù)端。
(5)補(bǔ)充:Query Then Fetch 的搜索類(lèi)型在文檔相關(guān)性打分的時(shí)候參考的是本分片的數(shù)據(jù),這樣在文檔數(shù)量較少的時(shí)候可能不夠準(zhǔn)確,DFS Query Then Fetch 增加了一個(gè)預(yù)查詢(xún)的處理,詢(xún)問(wèn) Term 和 Document frequency,這個(gè)評(píng)分更準(zhǔn)確,但是性能會(huì)變差。*

15、在 Elasticsearch 中,是怎么根據(jù)一個(gè)詞找到對(duì)應(yīng)的倒排索引的?
(1)Lucene的索引過(guò)程,就是按照全文檢索的基本過(guò)程,將倒排表寫(xiě)成此文件格式的過(guò)程。
(2)Lucene的搜索過(guò)程,就是按照此文件格式將索引進(jìn)去的信息讀出來(lái),然后計(jì)算每篇文檔打分(score)的過(guò)程。
16、Elasticsearch 在部署時(shí),對(duì) Linux 的設(shè)置有哪些優(yōu)化方法?
(1)64 GB 內(nèi)存的機(jī)器是非常理想的, 但是 32 GB 和 16 GB 機(jī)器也是很常見(jiàn)的。少于 8 GB 會(huì)適得其反。
(2)如果你要在更快的 CPUs 和更多的核心之間選擇,選擇更多的核心更好。多個(gè)內(nèi)核提供的額外并發(fā)遠(yuǎn)勝過(guò)稍微快一點(diǎn)點(diǎn)的時(shí)鐘頻率。
(3)如果你負(fù)擔(dān)得起 SSD,它將遠(yuǎn)遠(yuǎn)超出任何旋轉(zhuǎn)介質(zhì)。基于 SSD 的節(jié)點(diǎn),查詢(xún)和索引性能都有提升。如果你負(fù)擔(dān)得起,SSD 是一個(gè)好的選擇。
(4)即使數(shù)據(jù)中心們近在咫尺,也要避免集群跨越多個(gè)數(shù)據(jù)中心。絕對(duì)要避免集群跨越大的地理距離。
(5)請(qǐng)確保運(yùn)行你應(yīng)用程序的 JVM 和服務(wù)器的 JVM 是完全一樣的。在Elasticsearch 的幾個(gè)地方,使用 Java 的本地序列化。
(6)通過(guò)設(shè)置 gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time 可以在集群重啟的時(shí)候避免過(guò)多的分片交換,這可能會(huì)讓數(shù)據(jù)恢復(fù)從數(shù)個(gè)小時(shí)縮短為幾秒鐘。
(7)Elasticsearch 默認(rèn)被配置為使用單播發(fā)現(xiàn),以防止節(jié)點(diǎn)無(wú)意中加入集群。只有在同一臺(tái)機(jī)器上運(yùn)行的節(jié)點(diǎn)才會(huì)自動(dòng)組成集群。最好使用單播代替組播。
(8)不要隨意修改垃圾回收器(CMS)和各個(gè)線(xiàn)程池的大小。
(9)把你的內(nèi)存的(少于)一半給 Lucene(但不要超過(guò) 32 GB!),通過(guò)ES_HEAP_SIZE 環(huán)境變量設(shè)置。
(10)內(nèi)存交換到磁盤(pán)對(duì)服務(wù)器性能來(lái)說(shuō)是致命的。如果內(nèi)存交換到磁盤(pán)上,一個(gè)100 微秒的操作可能變成 10 毫秒。再想想那么多 10 微秒的操作時(shí)延累加起來(lái)。不難看出 swapping 對(duì)于性能是多么可怕。
(11)Lucene 使用了大 量 的文件。同時(shí),Elasticsearch 在節(jié)點(diǎn)和 HTTP 客戶(hù)端之間進(jìn)行通信也使用了大量的套接字。所有這一切都需要足夠的文件描述符。你應(yīng)該增加你的文件描述符,設(shè)置一個(gè)很大的值,如 64,000。
補(bǔ)充:索引階段性能提升方法
(1)使用批量請(qǐng)求并調(diào)整其大小:每次批量數(shù)據(jù) 5–15 MB 大是個(gè)不錯(cuò)的起始點(diǎn)。
(2)存儲(chǔ):使用 SSD
(3)段和合并:Elasticsearch 默認(rèn)值是 20 MB/s,對(duì)機(jī)械磁盤(pán)應(yīng)該是個(gè)不錯(cuò)的設(shè)置。如果你用的是 SSD,可以考慮提高到 100–200 MB/s。如果你在做批量導(dǎo)入,完全不在意搜索,你可以徹底關(guān)掉合并限流。另外還可以增加index.translog.flush_threshold_size 設(shè)置,從默認(rèn)的 512 MB 到更大一些的值,比如 1 GB,這可以在一次清空觸發(fā)的時(shí)候在事務(wù)日志里積累出更大的段。
(4)如果你的搜索結(jié)果不需要近實(shí)時(shí)的準(zhǔn)確度,考慮把每個(gè)索引的index.refresh_interval 改到 30s。
(5)如果你在做大批量導(dǎo)入,考慮通過(guò)設(shè)置 index.number_of_replicas: 0 關(guān)閉副本。
17、對(duì)于 GC 方面,在使用 Elasticsearch 時(shí)要注意什么?
(1)倒排詞典的索引需要常駐內(nèi)存,無(wú)法 GC,需要監(jiān)控 data node 上 segmentmemory 增長(zhǎng)趨勢(shì)。
(2)各類(lèi)緩存,field cache, filter cache, indexing cache, bulk queue 等等,要設(shè)置合理的大小,并且要應(yīng)該根據(jù)最壞的情況來(lái)看 heap 是否夠用,也就是各類(lèi)緩存全部占滿(mǎn)的時(shí)候,還有 heap 空間可以分配給其他任務(wù)嗎?避免采用 clear cache等“自欺欺人”的方式來(lái)釋放內(nèi)存。
(3)避免返回大量結(jié)果集的搜索與聚合。確實(shí)需要大量拉取數(shù)據(jù)的場(chǎng)景,可以采用scan & scroll api 來(lái)實(shí)現(xiàn)。
(4)cluster stats 駐留內(nèi)存并無(wú)法水平擴(kuò)展,超大規(guī)模集群可以考慮分拆成多個(gè)集群通過(guò) tribe node 連接。
(5)想知道 heap 夠不夠,必須結(jié)合實(shí)際應(yīng)用場(chǎng)景,并對(duì)集群的 heap 使用情況做持續(xù)的監(jiān)控。
(6)根據(jù)監(jiān)控?cái)?shù)據(jù)理解內(nèi)存需求,合理配置各類(lèi)circuit breaker,將內(nèi)存溢出風(fēng)險(xiǎn)降低到最低
18、Elasticsearch 對(duì)于大數(shù)據(jù)量(上億量級(jí))的聚合如何實(shí)現(xiàn)?
Elasticsearch 提供的首個(gè)近似聚合是 cardinality 度量。它提供一個(gè)字段的基數(shù),即該字段的 distinct 或者 unique 值的數(shù)目。它是基于 HLL 算法的。HLL 會(huì)先對(duì)我們的輸入作哈希運(yùn)算,然后根據(jù)哈希運(yùn)算的結(jié)果中的 bits 做概率估算從而得到基數(shù)。其特點(diǎn)是:可配置的精度,用來(lái)控制內(nèi)存的使用(更精確 = 更多內(nèi)存);小的數(shù)據(jù)集精度是非常高的;我們可以通過(guò)配置參數(shù),來(lái)設(shè)置去重需要的固定內(nèi)存使用量。無(wú)論數(shù)千還是數(shù)十億的唯一值,內(nèi)存使用量只與你配置的精確度相關(guān)。
19、在并發(fā)情況下,Elasticsearch 如果保證讀寫(xiě)一致?
(1)可以通過(guò)版本號(hào)使用樂(lè)觀并發(fā)控制,以確保新版本不會(huì)被舊版本覆蓋,由應(yīng)用層來(lái)處理具體的沖突;
(2)另外對(duì)于寫(xiě)操作,一致性級(jí)別支持 quorum/one/all,默認(rèn)為 quorum,即只有當(dāng)大多數(shù)分片可用時(shí)才允許寫(xiě)操作。但即使大多數(shù)可用,也可能存在因?yàn)榫W(wǎng)絡(luò)等原因?qū)е聦?xiě)入副本失敗,這樣該副本被認(rèn)為故障,分片將會(huì)在一個(gè)不同的節(jié)點(diǎn)上重建。
(3)對(duì)于讀操作,可以設(shè)置 replication 為 sync(默認(rèn)),這使得操作在主分片和副本分片都完成后才會(huì)返回;如果設(shè)置 replication 為 async 時(shí),也可以通過(guò)設(shè)置搜索請(qǐng)求參數(shù)_preference 為 primary 來(lái)查詢(xún)主分片,確保文檔是最新版本。
20、如何監(jiān)控 Elasticsearch 集群狀態(tài)?
Marvel 讓你可以很簡(jiǎn)單的通過(guò) Kibana 監(jiān)控 Elasticsearch。你可以實(shí)時(shí)查看你的集群健康狀態(tài)和性能,也可以分析過(guò)去的集群、索引和節(jié)點(diǎn)指標(biāo)。
21、介紹下你們電商搜索的整體技術(shù)架構(gòu)。

22、介紹一下你們的個(gè)性化搜索方案?
基于word2vec和Elasticsearch實(shí)現(xiàn)個(gè)性化搜索
(1)基于word2vec、Elasticsearch和自定義的腳本插件,我們就實(shí)現(xiàn)了一個(gè)個(gè)性化的搜索服務(wù),相對(duì)于原有的實(shí)現(xiàn),新版的點(diǎn)擊率和轉(zhuǎn)化率都有大幅的提升;
(2)基于word2vec的商品向量還有一個(gè)可用之處,就是可以用來(lái)實(shí)現(xiàn)相似商品的推薦;
(3)使用word2vec來(lái)實(shí)現(xiàn)個(gè)性化搜索或個(gè)性化推薦是有一定局限性的,因?yàn)樗荒芴幚碛脩?hù)點(diǎn)擊歷史這樣的時(shí)序數(shù)據(jù),而無(wú)法全面的去考慮用戶(hù)偏好,這個(gè)還是有很大的改進(jìn)和提升的空間;
23、是否了解字典樹(shù)?
常用字典數(shù)據(jù)結(jié)構(gòu)如下所示:

Trie 的核心思想是空間換時(shí)間,利用字符串的公共前綴來(lái)降低查詢(xún)時(shí)間的開(kāi)銷(xiāo)以達(dá)到提高效率的目的。它有 3 個(gè)基本性質(zhì):
1)根節(jié)點(diǎn)不包含字符,除根節(jié)點(diǎn)外每一個(gè)節(jié)點(diǎn)都只包含一個(gè)字符。
2)從根節(jié)點(diǎn)到某一節(jié)點(diǎn),路徑上經(jīng)過(guò)的字符連接起來(lái),為該節(jié)點(diǎn)對(duì)應(yīng)的字符串。
3)每個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)包含的字符都不相同。

(1)可以看到,trie 樹(shù)每一層的節(jié)點(diǎn)數(shù)是 26^i 級(jí)別的。所以為了節(jié)省空間,我們還可以用動(dòng)態(tài)鏈表,或者用數(shù)組來(lái)模擬動(dòng)態(tài)。而空間的花費(fèi),不會(huì)超過(guò)單詞數(shù)×單詞長(zhǎng)度。
(2)實(shí)現(xiàn):對(duì)每個(gè)結(jié)點(diǎn)開(kāi)一個(gè)字母集大小的數(shù)組,每個(gè)結(jié)點(diǎn)掛一個(gè)鏈表,使用左兒子右兄弟表示法記錄這棵樹(shù);
(3)對(duì)于中文的字典樹(shù),每個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)用一個(gè)哈希表存儲(chǔ),這樣就不用浪費(fèi)太大的空間,而且查詢(xún)速度上可以保留哈希的復(fù)雜度 O(1)。
24、拼寫(xiě)糾錯(cuò)是如何實(shí)現(xiàn)的?
(1)拼寫(xiě)糾錯(cuò)是基于編輯距離來(lái)實(shí)現(xiàn);編輯距離是一種標(biāo)準(zhǔn)的方法,它用來(lái)表示經(jīng)過(guò)插入、刪除和替換操作從一個(gè)字符串轉(zhuǎn)換到另外一個(gè)字符串的最小操作步數(shù);
(2)編輯距離的計(jì)算過(guò)程:比如要計(jì)算 batyu 和 beauty 的編輯距離,先創(chuàng)建一個(gè)7×8 的表(batyu 長(zhǎng)度為 5,coffee 長(zhǎng)度為 6,各加 2),接著,在如下位置填入黑色數(shù)字。其他格的計(jì)算過(guò)程是取以下三個(gè)值的最小值:
如果最上方的字符等于最左方的字符,則為左上方的數(shù)字。否則為左上方的數(shù)字+1。(對(duì)于 3,3 來(lái)說(shuō)為 0)
左方數(shù)字+1(對(duì)于 3,3 格來(lái)說(shuō)為 2)
上方數(shù)字+1(對(duì)于 3,3 格來(lái)說(shuō)為 2)
最終取右下角的值即為編輯距離的值 3。

對(duì)于拼寫(xiě)糾錯(cuò),我們考慮構(gòu)造一個(gè)度量空間(Metric Space),該空間內(nèi)任何關(guān)系滿(mǎn)足以下三條基本條件:
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)根據(jù)三角不等式,則滿(mǎn)足與 query 距離在 n 范圍內(nèi)的另一個(gè)字符轉(zhuǎn) B,其與 A的距離最大為 d+n,最小為 d-n。
(2)BK 樹(shù)的構(gòu)造就過(guò)程如下:每個(gè)節(jié)點(diǎn)有任意個(gè)子節(jié)點(diǎn),每條邊有個(gè)值表示編輯距離。所有子節(jié)點(diǎn)到父節(jié)點(diǎn)的邊上標(biāo)注 n 表示編輯距離恰好為 n。比如,我們有棵樹(shù)父節(jié)點(diǎn)是”book”和兩個(gè)子節(jié)點(diǎn)”cake”和”books”,”book”到”books”的邊標(biāo)號(hào) 1,”book”到”cake”的邊上標(biāo)號(hào) 4。從字典里構(gòu)造好樹(shù)后,無(wú)論何時(shí)你想插入新單詞時(shí),計(jì)算該單詞與根節(jié)點(diǎn)的編輯距離,并且查找數(shù)值為d(neweord, root)的邊。遞歸得與各子節(jié)點(diǎn)進(jìn)行比較,直到?jīng)]有子節(jié)點(diǎn),你就可以創(chuàng)建新的子節(jié)點(diǎn)并將新單詞保存在那。比如,插入”boo”到剛才上述例子的樹(shù)中,我們先檢查根節(jié)點(diǎn),查找 d(“book”, “boo”) = 1 的邊,然后檢查標(biāo)號(hào)為1 的邊的子節(jié)點(diǎn),得到單詞”books”。我們?cè)儆?jì)算距離 d(“books”, “boo”)=2,則將新單詞插在”books”之后,邊標(biāo)號(hào)為 2。
3、查詢(xún)相似詞如下:計(jì)算單詞與根節(jié)點(diǎn)的編輯距離 d,然后遞歸查找每個(gè)子節(jié)點(diǎn)標(biāo)號(hào)為 d-n 到 d+n(包含)的邊。假如被檢查的節(jié)點(diǎn)與搜索單詞的距離 d 小于 n,則返回該節(jié)點(diǎn)并繼續(xù)查詢(xún)。比如輸入 cape 且最大容忍距離為 1,則先計(jì)算和根的編輯距離 d(“book”, “cape”)=4,然后接著找和根節(jié)點(diǎn)之間編輯距離為 3 到5 的,這個(gè)就找到了 cake 這個(gè)節(jié)點(diǎn),計(jì)算 d(“cake”, “cape”)=1,滿(mǎn)足條件所以返回 cake,然后再找和 cake 節(jié)點(diǎn)編輯距離是 0 到 2 的,分別找到 cape 和cart 節(jié)點(diǎn),這樣就得到 cape 這個(gè)滿(mǎn)足條件的結(jié)果。

來(lái)源:程序員追風(fēng)
整理:大數(shù)據(jù)肌肉猿
--end--
