es的索引搜索是以lucene為底層的喷面,但是lucene是沒有實現(xiàn)分布式,lucene提供了核心的索引和搜索引擎航闺,ES則提供分布式和高可用奋刽。
lucene的工作原理可以見下面的這一篇博文:
ElasticSearch工作原理與插件
ElasticSearch 是一個基于lucene構(gòu)建的開源的滞磺,分布式的诫欠,restFul全文本搜索引擎涵卵。
1. 基本概念
Index(索引)
ES中的索引類似于傳統(tǒng)數(shù)據(jù)庫中的數(shù)據(jù)庫,ES中數(shù)據(jù)存儲于索引中荒叼,索引是具有類似特性的文檔的集合轿偎。
Type(類型)
類型類似于傳統(tǒng)庫中的表,類型是索引內(nèi)部的邏輯分區(qū)被廓,類型就是為那些擁有相同的域的文檔做的預(yù)定義坏晦。
document(文檔)
文檔是Lucene索引和搜索的原子單位,它是包含了一個或多個域的容器嫁乘,基于JSON格式進(jìn)行表示昆婿。
mapping(映射)
所有的文檔在存儲之前都要首先進(jìn)行分析。用戶可根據(jù)需要定義如何將文本分割成token蜓斧,哪些token應(yīng)該被過濾掉仓蛆,以及哪些文本需要進(jìn)行額外處理等等。
shard(分片)法精,replica(副本)
將一個索引內(nèi)部的數(shù)據(jù)分布地存儲于多個節(jié)點多律,它通過將一個索引切分為多個底層物理的Lucene索引完成索引數(shù)據(jù)的分割存儲功能痴突,這每一個物理的Lucene索引稱為一個分片(shard)。
每個分片其內(nèi)部都是一個全功能且獨立的索引狼荞,因此可由集群中的任何主機存儲辽装。創(chuàng)建索引時,用戶可指定其分片的數(shù)量相味,默認(rèn)數(shù)量為5個拾积。
Shard有兩種類型:primary和replica,即主shard及副本shard丰涉。
Primary shard用于文檔存儲拓巧,每個新的索引會自動創(chuàng)建5個Primary shard,當(dāng)然此數(shù)量可在索引創(chuàng)建之前通過配置自行定義一死,不過肛度,一旦創(chuàng)建完成,其Primary shard的數(shù)量將不可更改投慈。
Replica shard是Primary Shard的副本承耿,用于冗余數(shù)據(jù)及提高搜索性能。
每個Primary shard默認(rèn)配置了一個Replica shard伪煤,但也可以配置多個加袋,且其數(shù)量可動態(tài)更改。ES會根據(jù)需要自動增加或減少這些Replica shard的數(shù)量抱既。
ES集群可由多個節(jié)點組成职烧,各Shard分布式地存儲于這些節(jié)點上。
ES可自動在節(jié)點間按需要移動shard防泵,例如增加節(jié)點或節(jié)點故障時蚀之。簡而言之,分片實現(xiàn)了集群的分布式存儲捷泞,而副本實現(xiàn)了其分布式處理及冗余功能恬总。
ES的restFul
ElasticSearch提供了易用但功能強大的RESTful API以用于與集群進(jìn)行交互,這些API大體可分為如下四類:
(1) 檢查集群肚邢、節(jié)點、索引等健康與否拭卿,以及獲取其相關(guān)狀態(tài)與統(tǒng)計信息骡湖;
(2) 管理集群、節(jié)點峻厚、索引數(shù)據(jù)及元數(shù)據(jù)响蕴;
(3) 執(zhí)行CRUD操作及搜索操作;
(4) 執(zhí)行高級搜索操作惠桃,例如paging浦夷、filtering辖试、scripting、faceting劈狐、aggregations及其它操作罐孝;
ES的讀寫原理
(1)es寫數(shù)據(jù)過程
1)客戶端隨機選擇一個node發(fā)送請求過去,這個node就是coordinating node(協(xié)調(diào)節(jié)點)
2)coordinating node肥缔,對document進(jìn)行路由莲兢,將請求轉(zhuǎn)發(fā)給對應(yīng)的node(有primary shard)
3)實際的node上的primary shard處理請求,然后將數(shù)據(jù)同步到replica node
4)coordinating node续膳,如果發(fā)現(xiàn)primary node和所有replica node都搞定之后改艇,就返回響應(yīng)結(jié)果給客戶端
在寫primary的過程中同時還要持久到本地 :
1)先寫入buffer,在buffer里的時候數(shù)據(jù)是搜索不到的坟岔;同時將數(shù)據(jù)寫入translog日志文件
2)如果buffer快滿了谒兄,或者到一定時間,就會將buffer數(shù)據(jù)refresh到一個新的segment file中社付,但是此時數(shù)據(jù)不是直接進(jìn)入segment file的磁盤文件的承疲,而是先進(jìn)入os cache的。這個過程就是refresh瘦穆。
每隔1秒鐘纪隙,es將buffer中的數(shù)據(jù)寫入一個新的segment file,每秒鐘會產(chǎn)生一個新的磁盤文件扛或,segment file绵咱,這個segment file中就存儲最近1秒內(nèi)buffer中寫入的數(shù)據(jù)
但是如果buffer里面此時沒有數(shù)據(jù),那當(dāng)然不會執(zhí)行refresh操作咯熙兔,每秒創(chuàng)建換一個空的segment file悲伶,如果buffer里面有數(shù)據(jù),默認(rèn)1秒鐘執(zhí)行一次refresh操作住涉,刷入一個新的segment file中
操作系統(tǒng)里面麸锉,磁盤文件其實都有一個東西,叫做os cache舆声,操作系統(tǒng)緩存花沉,就是說數(shù)據(jù)寫入磁盤文件之前,會先進(jìn)入os cache媳握,先進(jìn)入操作系統(tǒng)級別的一個內(nèi)存緩存中去
只要buffer中的數(shù)據(jù)被refresh操作碱屁,刷入os cache中,就代表這個數(shù)據(jù)就可以被搜索到了
為什么叫es是準(zhǔn)實時的蛾找?NRT娩脾,near real-time,準(zhǔn)實時打毛。默認(rèn)是每隔1秒refresh一次的柿赊,所以es是準(zhǔn)實時的俩功,因為寫入的數(shù)據(jù)1秒之后才能被看到。
可以通過es的restful api或者java api碰声,手動執(zhí)行一次refresh操作诡蜓,就是手動將buffer中的數(shù)據(jù)刷入os cache中,讓數(shù)據(jù)立馬就可以被搜索到奥邮。
只要數(shù)據(jù)被輸入os cache中万牺,buffer就會被清空了,因為不需要保留buffer了洽腺,數(shù)據(jù)在translog里面已經(jīng)持久化到磁盤去一份了
3)只要數(shù)據(jù)進(jìn)入os cache脚粟,此時就可以讓這個segment file的數(shù)據(jù)對外提供搜索了
4)重復(fù)1~3步驟,新的數(shù)據(jù)不斷進(jìn)入buffer和translog蘸朋,不斷將buffer數(shù)據(jù)寫入一個又一個新的segment file中去核无,每次refresh完buffer清空,translog保留藕坯。隨著這個過程推進(jìn)团南,translog會變得越來越大。當(dāng)translog達(dá)到一定長度的時候炼彪,就會觸發(fā)commit操作吐根。
buffer中的數(shù)據(jù),倒是好辐马,每隔1秒就被刷到os cache中去拷橘,然后這個buffer就被清空了。所以說這個buffer的數(shù)據(jù)始終是可以保持住不會填滿es進(jìn)程的內(nèi)存的喜爷。
每次一條數(shù)據(jù)寫入buffer冗疮,同時會寫入一條日志到translog日志文件中去,所以這個translog日志文件是不斷變大的檩帐,當(dāng)translog日志文件大到一定程度的時候术幔,就會執(zhí)行commit操作。
5)commit操作發(fā)生第一步湃密,就是將buffer中現(xiàn)有數(shù)據(jù)refresh到os cache中去诅挑,清空buffer
6)將一個commit point寫入磁盤文件,里面標(biāo)識著這個commit point對應(yīng)的所有segment file
7)強行將os cache中目前所有的數(shù)據(jù)都fsync到磁盤文件中去
translog日志文件的作用是什么泛源?就是在你執(zhí)行commit操作之前揍障,數(shù)據(jù)要么是停留在buffer中,要么是停留在os cache中俩由,無論是buffer還是os cache都是內(nèi)存,一旦這臺機器死了癌蚁,內(nèi)存中的數(shù)據(jù)就全丟了幻梯。
所以需要將數(shù)據(jù)對應(yīng)的操作寫入一個專門的日志文件兜畸,translog日志文件中,一旦此時機器宕機碘梢,再次重啟的時候咬摇,es會自動讀取translog日志文件中的數(shù)據(jù),恢復(fù)到內(nèi)存buffer和os cache中去煞躬。
commit操作:1肛鹏、寫commit point;2恩沛、將os cache數(shù)據(jù)fsync強刷到磁盤上去在扰;3陷揪、清空translog日志文件
8)將現(xiàn)有的translog清空柿顶,然后再次重啟啟用一個translog,此時commit操作完成拄轻。默認(rèn)每隔30分鐘會自動執(zhí)行一次commit搅裙,但是如果translog過大皱卓,也會觸發(fā)commit。整個commit的過程部逮,叫做flush操作娜汁。我們可以手動執(zhí)行flush操作,就是將所有os cache數(shù)據(jù)刷到磁盤文件中去兄朋。
不叫做commit操作掐禁,flush操作。es中的flush操作蜈漓,就對應(yīng)著commit的全過程穆桂。我們也可以通過es api,手動執(zhí)行flush操作融虽,手動將os cache中的數(shù)據(jù)fsync強刷到磁盤上去享完,記錄一個commit point,清空translog日志文件有额。
9)translog其實也是先寫入os cache的般又,默認(rèn)每隔5秒刷一次到磁盤中去,所以默認(rèn)情況下巍佑,可能有5秒的數(shù)據(jù)會僅僅停留在buffer或者translog文件的os cache中茴迁,如果此時機器掛了,會丟失5秒鐘的數(shù)據(jù)萤衰。但是這樣性能比較好堕义,最多丟5秒的數(shù)據(jù)。也可以將translog設(shè)置成每次寫操作必須是直接fsync到磁盤脆栋,但是性能會差很多倦卖。
實際上你在這里洒擦,如果面試官沒有問你es丟數(shù)據(jù)的問題,你可以在這里給面試官炫一把怕膛,你說熟嫩,其實es第一是準(zhǔn)實時的,數(shù)據(jù)寫入1秒后可以搜索到褐捻;可能會丟失數(shù)據(jù)的掸茅,你的數(shù)據(jù)有5秒的數(shù)據(jù),停留在buffer柠逞、translog os cache昧狮、segment file os cache中,有5秒的數(shù)據(jù)不在磁盤上边苹,此時如果宕機陵且,會導(dǎo)致5秒的數(shù)據(jù)丟失。
如果你希望一定不能丟失數(shù)據(jù)的話个束,你可以設(shè)置個參數(shù)慕购,官方文檔,百度一下茬底。每次寫入一條數(shù)據(jù)沪悲,都是寫入buffer,同時寫入磁盤上的translog阱表,但是這會導(dǎo)致寫性能殿如、寫入吞吐量會下降一個數(shù)量級。本來一秒鐘可以寫2000條最爬,現(xiàn)在你一秒鐘只能寫200條涉馁,都有可能。
10)如果是刪除操作爱致,commit的時候會生成一個.del文件烤送,里面將某個doc標(biāo)識為deleted狀態(tài),那么搜索的時候根據(jù).del文件就知道這個doc被刪除了
11)如果是更新操作糠悯,就是將原來的doc標(biāo)識為deleted狀態(tài)帮坚,然后新寫入一條數(shù)據(jù)
12)buffer每次refresh一次,就會產(chǎn)生一個segment file互艾,所以默認(rèn)情況下是1秒鐘一個segment file试和,segment file會越來越多,此時會定期執(zhí)行merge
13)每次merge的時候纫普,會將多個segment file合并成一個阅悍,同時這里會將標(biāo)識為deleted的doc給物理刪除掉,然后將新的segment file寫入磁盤,這里會寫一個commit point溉箕,標(biāo)識所有新的segment file晦墙,然后打開segment file供搜索使用,同時刪除舊的segment file肴茄。
es里的寫流程,有4個底層的核心概念但指,refresh寡痰、flush、translog棋凳、merge
當(dāng)segment file多到一定程度的時候拦坠,es就會自動觸發(fā)merge操作,將多個segment file給merge成一個segment file剩岳。
(2)es讀數(shù)據(jù)過程
查詢贞滨,GET某一條數(shù)據(jù),寫入了某個document拍棕,這個document會自動給你分配一個全局唯一的id晓铆,doc id,同時也是根據(jù)doc id進(jìn)行hash路由到對應(yīng)的primary shard上面去绰播。也可以手動指定doc id骄噪,比如用訂單id,用戶id蠢箩。
你可以通過doc id來查詢链蕊,會根據(jù)doc id進(jìn)行hash,判斷出來當(dāng)時把doc id分配到了哪個shard上面去谬泌,從那個shard去查詢
1)客戶端發(fā)送請求到任意一個node滔韵,成為coordinate node
2)coordinate node對document進(jìn)行路由,將請求轉(zhuǎn)發(fā)到對應(yīng)的node掌实,此時會使用round-robin隨機輪詢算法陪蜻,在primary shard以及其所有replica中隨機選擇一個,讓讀請求負(fù)載均衡
3)接收請求的node返回document給coordinate node
4)coordinate node返回document給客戶端
(3)es搜索數(shù)據(jù)過程
1)客戶端發(fā)送請求到一個coordinate node
2)協(xié)調(diào)節(jié)點將搜索請求轉(zhuǎn)發(fā)到所有的shard對應(yīng)的primary shard或replica shard也可以
3)query phase:每個shard將自己的搜索結(jié)果(其實就是一些doc id)潮峦,返回給協(xié)調(diào)節(jié)點囱皿,由協(xié)調(diào)節(jié)點進(jìn)行數(shù)據(jù)的合并、排序忱嘹、分頁等操作嘱腥,產(chǎn)出最終結(jié)果
4)fetch phase:接著由協(xié)調(diào)節(jié)點,根據(jù)doc id去各個節(jié)點上拉取實際的document數(shù)據(jù)拘悦,最終返回給客戶端
(4)搜索的底層原理齿兔,倒排索引,畫圖說明傳統(tǒng)數(shù)據(jù)庫和倒排索引的區(qū)別