面试系列八 es写入数据的工作原理
(1)es寫(xiě)數(shù)據(jù)過(guò)程
?
1)客戶(hù)端選擇一個(gè)node發(fā)送請(qǐng)求過(guò)去,這個(gè)node就是coordinating node(協(xié)調(diào)節(jié)點(diǎn))
2)coordinating node,對(duì)document進(jìn)行路由,將請(qǐng)求轉(zhuǎn)發(fā)給對(duì)應(yīng)的node(有primary shard)
3)實(shí)際的node上的primary shard處理請(qǐng)求,然后將數(shù)據(jù)同步到replica node
4)coordinating node,如果發(fā)現(xiàn)primary node和所有replica node都搞定之后,就返回響應(yīng)結(jié)果給客戶(hù)端
?
(2)es讀數(shù)據(jù)過(guò)程
?
查詢(xún),GET某一條數(shù)據(jù),寫(xiě)入了某個(gè)document,這個(gè)document會(huì)自動(dòng)給你分配一個(gè)全局唯一的id,doc id,同時(shí)也是根據(jù)doc id進(jìn)行hash路由到對(duì)應(yīng)的primary shard上面去。也可以手動(dòng)指定doc id,比如用訂單id,用戶(hù)id。
?
你可以通過(guò)doc id來(lái)查詢(xún),會(huì)根據(jù)doc id進(jìn)行hash,判斷出來(lái)當(dāng)時(shí)把doc id分配到了哪個(gè)shard上面去,從那個(gè)shard去查詢(xún)
?
1)客戶(hù)端發(fā)送請(qǐng)求到任意一個(gè)node,成為coordinate node
2)coordinate node對(duì)document進(jìn)行路由,將請(qǐng)求轉(zhuǎn)發(fā)到對(duì)應(yīng)的node,此時(shí)會(huì)使用round-robin隨機(jī)輪詢(xún)算法,在primary shard以及其所有replica中隨機(jī)選擇一個(gè),讓讀請(qǐng)求負(fù)載均衡
3)接收請(qǐng)求的node返回document給coordinate node
4)coordinate node返回document給客戶(hù)端
?
(3)es搜索數(shù)據(jù)過(guò)程
?
es最強(qiáng)大的是做全文檢索,就是比如你有三條數(shù)據(jù)
?
java真好玩兒啊
java好難學(xué)啊
j2ee特別牛
?
你根據(jù)java關(guān)鍵詞來(lái)搜索,將包含java的document給搜索出來(lái)
?
es就會(huì)給你返回:java真好玩兒啊,java好難學(xué)啊
?
1)客戶(hù)端發(fā)送請(qǐng)求到一個(gè)coordinate node
2)協(xié)調(diào)節(jié)點(diǎn)將搜索請(qǐng)求轉(zhuǎn)發(fā)到所有的shard對(duì)應(yīng)的primary shard或replica shard也可以
3)query phase:每個(gè)shard將自己的搜索結(jié)果(其實(shí)就是一些doc id),返回給協(xié)調(diào)節(jié)點(diǎn),由協(xié)調(diào)節(jié)點(diǎn)進(jìn)行數(shù)據(jù)的合并、排序、分頁(yè)等操作,產(chǎn)出最終結(jié)果
4)fetch phase:接著由協(xié)調(diào)節(jié)點(diǎn),根據(jù)doc id去各個(gè)節(jié)點(diǎn)上拉取實(shí)際的document數(shù)據(jù),最終返回給客戶(hù)端
?
(4)搜索的底層原理,倒排索引,畫(huà)圖說(shuō)明傳統(tǒng)數(shù)據(jù)庫(kù)和倒排索引的區(qū)別
?
(5)寫(xiě)數(shù)據(jù)底層原理
?
1)先寫(xiě)入buffer,在buffer里的時(shí)候數(shù)據(jù)是搜索不到的;同時(shí)將數(shù)據(jù)寫(xiě)入translog日志文件
?
2)如果buffer快滿(mǎn)了,或者到一定時(shí)間,就會(huì)將buffer數(shù)據(jù)refresh到一個(gè)新的segment file中,但是此時(shí)數(shù)據(jù)不是直接進(jìn)入segment file的磁盤(pán)文件的,而是先進(jìn)入os cache的。這個(gè)過(guò)程就是refresh。
?
每隔1秒鐘,es將buffer中的數(shù)據(jù)寫(xiě)入一個(gè)新的segment file,每秒鐘會(huì)產(chǎn)生一個(gè)新的磁盤(pán)文件,segment file,這個(gè)segment file中就存儲(chǔ)最近1秒內(nèi)buffer中寫(xiě)入的數(shù)據(jù)
?
但是如果buffer里面此時(shí)沒(méi)有數(shù)據(jù),那當(dāng)然不會(huì)執(zhí)行refresh操作咯,每秒創(chuàng)建換一個(gè)空的segment file,如果buffer里面有數(shù)據(jù),默認(rèn)1秒鐘執(zhí)行一次refresh操作,刷入一個(gè)新的segment file中
?
操作系統(tǒng)里面,磁盤(pán)文件其實(shí)都有一個(gè)東西,叫做os cache,操作系統(tǒng)緩存,就是說(shuō)數(shù)據(jù)寫(xiě)入磁盤(pán)文件之前,會(huì)先進(jìn)入os cache,先進(jìn)入操作系統(tǒng)級(jí)別的一個(gè)內(nèi)存緩存中去
?
只要buffer中的數(shù)據(jù)被refresh操作,刷入os cache中,就代表這個(gè)數(shù)據(jù)就可以被搜索到了
?
為什么叫es是準(zhǔn)實(shí)時(shí)的?NRT,near real-time,準(zhǔn)實(shí)時(shí)。默認(rèn)是每隔1秒refresh一次的,所以es是準(zhǔn)實(shí)時(shí)的,因?yàn)閷?xiě)入的數(shù)據(jù)1秒之后才能被看到。
?
可以通過(guò)es的restful api或者java api,手動(dòng)執(zhí)行一次refresh操作,就是手動(dòng)將buffer中的數(shù)據(jù)刷入os cache中,讓數(shù)據(jù)立馬就可以被搜索到。
?
只要數(shù)據(jù)被輸入os cache中,buffer就會(huì)被清空了,因?yàn)椴恍枰A鬮uffer了,數(shù)據(jù)在translog里面已經(jīng)持久化到磁盤(pán)去一份了
?
3)只要數(shù)據(jù)進(jìn)入os cache,此時(shí)就可以讓這個(gè)segment file的數(shù)據(jù)對(duì)外提供搜索了
?
4)重復(fù)1~3步驟,新的數(shù)據(jù)不斷進(jìn)入buffer和translog,不斷將buffer數(shù)據(jù)寫(xiě)入一個(gè)又一個(gè)新的segment file中去,每次refresh完buffer清空,translog保留。隨著這個(gè)過(guò)程推進(jìn),translog會(huì)變得越來(lái)越大。當(dāng)translog達(dá)到一定長(zhǎng)度的時(shí)候,就會(huì)觸發(fā)commit操作。
?
buffer中的數(shù)據(jù),倒是好,每隔1秒就被刷到os cache中去,然后這個(gè)buffer就被清空了。所以說(shuō)這個(gè)buffer的數(shù)據(jù)始終是可以保持住不會(huì)填滿(mǎn)es進(jìn)程的內(nèi)存的。
?
每次一條數(shù)據(jù)寫(xiě)入buffer,同時(shí)會(huì)寫(xiě)入一條日志到translog日志文件中去,所以這個(gè)translog日志文件是不斷變大的,當(dāng)translog日志文件大到一定程度的時(shí)候,就會(huì)執(zhí)行commit操作。
?
5)commit操作發(fā)生第一步,就是將buffer中現(xiàn)有數(shù)據(jù)refresh到os cache中去,清空buffer
?
6)將一個(gè)commit point寫(xiě)入磁盤(pán)文件,里面標(biāo)識(shí)著這個(gè)commit point對(duì)應(yīng)的所有segment file
?
7)強(qiáng)行將os cache中目前所有的數(shù)據(jù)都fsync到磁盤(pán)文件中去
?
translog日志文件的作用是什么?就是在你執(zhí)行commit操作之前,數(shù)據(jù)要么是停留在buffer中,要么是停留在os cache中,無(wú)論是buffer還是os cache都是內(nèi)存,一旦這臺(tái)機(jī)器死了,內(nèi)存中的數(shù)據(jù)就全丟了。
?
所以需要將數(shù)據(jù)對(duì)應(yīng)的操作寫(xiě)入一個(gè)專(zhuān)門(mén)的日志文件,translog日志文件中,一旦此時(shí)機(jī)器宕機(jī),再次重啟的時(shí)候,es會(huì)自動(dòng)讀取translog日志文件中的數(shù)據(jù),恢復(fù)到內(nèi)存buffer和os cache中去。
?
commit操作:1、寫(xiě)commit point;2、將os cache數(shù)據(jù)fsync強(qiáng)刷到磁盤(pán)上去;3、清空translog日志文件
?
8)將現(xiàn)有的translog清空,然后再次重啟啟用一個(gè)translog,此時(shí)commit操作完成。默認(rèn)每隔30分鐘會(huì)自動(dòng)執(zhí)行一次commit,但是如果translog過(guò)大,也會(huì)觸發(fā)commit。整個(gè)commit的過(guò)程,叫做flush操作。我們可以手動(dòng)執(zhí)行flush操作,就是將所有os cache數(shù)據(jù)刷到磁盤(pán)文件中去。
?
不叫做commit操作,flush操作。es中的flush操作,就對(duì)應(yīng)著commit的全過(guò)程。我們也可以通過(guò)es api,手動(dòng)執(zhí)行flush操作,手動(dòng)將os cache中的數(shù)據(jù)fsync強(qiáng)刷到磁盤(pán)上去,記錄一個(gè)commit point,清空translog日志文件。
?
9)translog其實(shí)也是先寫(xiě)入os cache的,默認(rèn)每隔5秒刷一次到磁盤(pán)中去,所以默認(rèn)情況下,可能有5秒的數(shù)據(jù)會(huì)僅僅停留在buffer或者translog文件的os cache中,如果此時(shí)機(jī)器掛了,會(huì)丟失5秒鐘的數(shù)據(jù)。但是這樣性能比較好,最多丟5秒的數(shù)據(jù)。也可以將translog設(shè)置成每次寫(xiě)操作必須是直接fsync到磁盤(pán),但是性能會(huì)差很多。
?
實(shí)際上你在這里,如果面試官?zèng)]有問(wèn)你es丟數(shù)據(jù)的問(wèn)題,你可以在這里給面試官炫一把,你說(shuō),其實(shí)es第一是準(zhǔn)實(shí)時(shí)的,數(shù)據(jù)寫(xiě)入1秒后可以搜索到;可能會(huì)丟失數(shù)據(jù)的,你的數(shù)據(jù)有5秒的數(shù)據(jù),停留在buffer、translog os cache、segment file os cache中,有5秒的數(shù)據(jù)不在磁盤(pán)上,此時(shí)如果宕機(jī),會(huì)導(dǎo)致5秒的數(shù)據(jù)丟失。
?
如果你希望一定不能丟失數(shù)據(jù)的話(huà),你可以設(shè)置個(gè)參數(shù),官方文檔,百度一下。每次寫(xiě)入一條數(shù)據(jù),都是寫(xiě)入buffer,同時(shí)寫(xiě)入磁盤(pán)上的translog,但是這會(huì)導(dǎo)致寫(xiě)性能、寫(xiě)入吞吐量會(huì)下降一個(gè)數(shù)量級(jí)。本來(lái)一秒鐘可以寫(xiě)2000條,現(xiàn)在你一秒鐘只能寫(xiě)200條,都有可能。
?
10)如果是刪除操作,commit的時(shí)候會(huì)生成一個(gè).del文件,里面將某個(gè)doc標(biāo)識(shí)為deleted狀態(tài),那么搜索的時(shí)候根據(jù).del文件就知道這個(gè)doc被刪除了
?
11)如果是更新操作,就是將原來(lái)的doc標(biāo)識(shí)為deleted狀態(tài),然后新寫(xiě)入一條數(shù)據(jù)
?
12)buffer每次refresh一次,就會(huì)產(chǎn)生一個(gè)segment file,所以默認(rèn)情況下是1秒鐘一個(gè)segment file,segment file會(huì)越來(lái)越多,此時(shí)會(huì)定期執(zhí)行merge
?
13)每次merge的時(shí)候,會(huì)將多個(gè)segment file合并成一個(gè),同時(shí)這里會(huì)將標(biāo)識(shí)為deleted的doc給物理刪除掉,然后將新的segment file寫(xiě)入磁盤(pán),這里會(huì)寫(xiě)一個(gè)commit point,標(biāo)識(shí)所有新的segment file,然后打開(kāi)segment file供搜索使用,同時(shí)刪除舊的segment file。
?
es里的寫(xiě)流程,有4個(gè)底層的核心概念,refresh、flush、translog、merge
?
當(dāng)segment file多到一定程度的時(shí)候,es就會(huì)自動(dòng)觸發(fā)merge操作,將多個(gè)segment file給merge成一個(gè)segment file。
轉(zhuǎn)載于:https://www.cnblogs.com/xiufengchen/p/11258901.html
總結(jié)
以上是生活随笔為你收集整理的面试系列八 es写入数据的工作原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: ivew 限制输入 0 到 1 的数字
- 下一篇: 学习旧岛小程序 (1) flex
