es 寫入數(shù)據(jù)的工作原理是什么安芴濉?es 查詢數(shù)據(jù)的工作原理是什么跋趵谩箕别?底層的 lucene 介紹一下唄?倒排索引了解嗎滞谢?

面試題

es 寫入數(shù)據(jù)的工作原理是什么按 ?es 查詢數(shù)據(jù)的工作原理是什么笆ㄑ睢母截?底層的 lucene 介紹一下唄?倒排索引了解嗎橄教?

面試官心理分析

問這個清寇,其實面試官就是要看看你了解不了解 es 的一些基本原理,因為用 es 無非就是寫入數(shù)據(jù)护蝶,搜索數(shù)據(jù)华烟。你要是不明白你發(fā)起一個寫入和搜索請求的時候,es 在干什么持灰,那你真的是......

對 es 基本就是個黑盒盔夜,你還能干啥?你唯一能干的就是用 es 的 api 讀寫數(shù)據(jù)了。要是出點什么問題喂链,你啥都不知道返十,那還能指望你什么呢?

面試題剖析

es 寫數(shù)據(jù)過程

  • 客戶端選擇一個 node 發(fā)送請求過去椭微,這個 node 就是 coordinating node(協(xié)調(diào)節(jié)點)洞坑。
  • coordinating node 對 document 進行路由,將請求轉(zhuǎn)發(fā)給對應(yīng)的 node(有 primary shard)蝇率。
  • 實際的 node 上的 primary shard 處理請求检诗,然后將數(shù)據(jù)同步到 replica node
  • coordinating node 如果發(fā)現(xiàn) primary node 和所有 replica node 都搞定之后瓢剿,就返回響應(yīng)結(jié)果給客戶端。
    es-write

es 讀數(shù)據(jù)過程

可以通過 doc id 來查詢悠轩,會根據(jù) doc id 進行 hash间狂,判斷出來當時把 doc id 分配到了哪個 shard 上面去,從那個 shard 去查詢火架。

  • 客戶端發(fā)送請求到任意一個 node鉴象,成為 coordinate node
  • coordinate nodedoc id 進行哈希路由何鸡,將請求轉(zhuǎn)發(fā)到對應(yīng)的 node纺弊,此時會使用 round-robin 隨機輪詢算法,在 primary shard 以及其所有 replica 中隨機選擇一個骡男,讓讀請求負載均衡淆游。
  • 接收請求的 node 返回 document 給 coordinate node
  • coordinate node 返回 document 給客戶端隔盛。

es 搜索數(shù)據(jù)過程

es 最強大的是做全文檢索犹菱,就是比如你有三條數(shù)據(jù):

java真好玩兒啊
java好難學(xué)啊
j2ee特別牛

你根據(jù) java 關(guān)鍵詞來搜索,將包含 javadocument 給搜索出來吮炕。es 就會給你返回:java真好玩兒啊腊脱,java好難學(xué)啊。

  • 客戶端發(fā)送請求到一個 coordinate node龙亲。
  • 協(xié)調(diào)節(jié)點將搜索請求轉(zhuǎn)發(fā)到所有的 shard 對應(yīng)的 primary shardreplica shard陕凹,都可以。
  • query phase:每個 shard 將自己的搜索結(jié)果(其實就是一些 doc id)返回給協(xié)調(diào)節(jié)點鳄炉,由協(xié)調(diào)節(jié)點進行數(shù)據(jù)的合并杜耙、排序、分頁等操作拂盯,產(chǎn)出最終結(jié)果泥技。
  • fetch phase:接著由協(xié)調(diào)節(jié)點根據(jù) doc id 去各個節(jié)點上拉取實際document 數(shù)據(jù),最終返回給客戶端。

寫數(shù)據(jù)底層原理

es-write-detail

先寫入內(nèi)存 buffer珊豹,在 buffer 里的時候數(shù)據(jù)是搜索不到的簸呈;同時將數(shù)據(jù)寫入 translog 日志文件。

如果 buffer 快滿了店茶,或者到一定時間蜕便,就會將內(nèi)存 buffer 數(shù)據(jù) refresh 到一個新的 segment file 中,但是此時數(shù)據(jù)不是直接進入 segment file 磁盤文件贩幻,而是先進入 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ù)仿荆,那當然不會執(zhí)行 refresh 操作,如果buffer里面有數(shù)據(jù)坏平,默認 1 秒鐘執(zhí)行一次 refresh 操作拢操,刷入一個新的 segment file 中。

操作系統(tǒng)里面舶替,磁盤文件其實都有一個東西令境,叫做 os cache,即操作系統(tǒng)緩存顾瞪,就是說數(shù)據(jù)寫入磁盤文件之前舔庶,會先進入 os cache,先進入操作系統(tǒng)級別的一個內(nèi)存緩存中去陈醒。只要 buffer 中的數(shù)據(jù)被 refresh 操作刷入 os cache中栖茉,這個數(shù)據(jù)就可以被搜索到了。

為什么叫 es 是準實時的孵延? NRT吕漂,全稱 near real-time。默認是每隔 1 秒 refresh 一次的尘应,所以 es 是準實時的惶凝,因為寫入的數(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)持久化到磁盤去一份了油湖。

重復(fù)上面的步驟,新的數(shù)據(jù)不斷進入 buffer 和 translog领跛,不斷將 buffer 數(shù)據(jù)寫入一個又一個新的 segment file 中去乏德,每次 refresh 完 buffer 清空,translog保留吠昭。隨著這個過程推進喊括,translog 會變得越來越大。當 translog 達到一定長度的時候矢棚,就會觸發(fā) commit 操作郑什。

commit 操作發(fā)生第一步,就是將 buffer 中現(xiàn)有數(shù)據(jù) refreshos cache 中去蒲肋,清空 buffer蘑拯。然后,將一個 commit point 寫入磁盤文件肉津,里面標識著這個 commit point 對應(yīng)的所有 segment file,同時強行將 os cache 中目前所有的數(shù)據(jù)都 fsync 到磁盤文件中去舱沧。最后清空 現(xiàn)有 translog 日志文件妹沙,重啟一個 translog,此時 commit 操作完成熟吏。

這個 commit 操作叫做 flush距糖。默認 30 分鐘自動執(zhí)行一次 flush,但如果 translog 過大牵寺,也會觸發(fā) flush悍引。flush 操作就對應(yīng)著 commit 的全過程,我們可以通過 es api帽氓,手動執(zhí)行 flush 操作趣斤,手動將 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 中去吗浩。

translog 其實也是先寫入 os cache 的,默認每隔 5 秒刷一次到磁盤中去浴滴,所以默認情況下拓萌,可能有 5 秒的數(shù)據(jù)會僅僅停留在 buffer 或者 translog 文件的 os cache 中,如果此時機器掛了升略,會丟失 5 秒鐘的數(shù)據(jù)微王。但是這樣性能比較好,最多丟 5 秒的數(shù)據(jù)品嚣。也可以將 translog 設(shè)置成每次寫操作必須是直接 fsync 到磁盤炕倘,但是性能會差很多。

實際上你在這里翰撑,如果面試官沒有問你 es 丟數(shù)據(jù)的問題罩旋,你可以在這里給面試官炫一把,你說眶诈,其實 es 第一是準實時的涨醋,數(shù)據(jù)寫入 1 秒后可以搜索到;可能會丟失數(shù)據(jù)的逝撬。有 5 秒的數(shù)據(jù)浴骂,停留在 buffer、translog os cache宪潮、segment file os cache 中溯警,而不在磁盤上,此時如果宕機狡相,會導(dǎo)致 5 秒的數(shù)據(jù)丟失梯轻。

數(shù)據(jù)寫入 segment file 之后,同時就建立好了倒排索引尽棕。

刪除/更新數(shù)據(jù)底層原理

如果是刪除操作喳挑,commit 的時候會生成一個 .del 文件,里面將某個 doc 標識為 deleted 狀態(tài)滔悉,那么搜索的時候根據(jù) .del 文件就知道這個 doc 是否被刪除了蟀悦。

如果是更新操作,就是將原來的 doc 標識為 deleted 狀態(tài)氧敢,然后新寫入一條數(shù)據(jù)日戈。

buffer 每次 refresh 一次,就會產(chǎn)生一個 segment file孙乖,所以默認情況下是 1 秒鐘一個 segment file浙炼,這樣下來 segment file 會越來越多份氧,此時會定期執(zhí)行 merge。每次 merge 的時候弯屈,會將多個 segment file 合并成一個蜗帜,同時這里會將標識為 deleted 的 doc 給物理刪除掉,然后將新的 segment file 寫入磁盤资厉,這里會寫一個 commit point厅缺,標識所有新的 segment file,然后打開 segment file 供搜索使用宴偿,同時刪除舊的 segment file湘捎。

底層 lucene

簡單來說,lucene 就是一個 jar 包窄刘,里面包含了封裝好的各種建立倒排索引的算法代碼窥妇。我們用 Java 開發(fā)的時候,引入 lucene jar娩践,然后基于 lucene 的 api 去開發(fā)就可以了活翩。

通過 lucene,我們可以將已有的數(shù)據(jù)建立索引翻伺,lucene 會在本地磁盤上面材泄,給我們組織索引的數(shù)據(jù)結(jié)構(gòu)。

倒排索引

在搜索引擎中吨岭,每個文檔都有一個對應(yīng)的文檔 ID拉宗,文檔內(nèi)容被表示為一系列關(guān)鍵詞的集合。例如未妹,文檔 1 經(jīng)過分詞簿废,提取了 20 個關(guān)鍵詞空入,每個關(guān)鍵詞都會記錄它在文檔中出現(xiàn)的次數(shù)和出現(xiàn)位置络它。

那么,倒排索引就是關(guān)鍵詞到文檔 ID 的映射歪赢,每個關(guān)鍵詞都對應(yīng)著一系列的文件化戳,這些文件中都出現(xiàn)了關(guān)鍵詞。

舉個栗子埋凯。

有以下文檔:

DocId Doc
1 谷歌地圖之父跳槽 Facebook
2 谷歌地圖之父加盟 Facebook
3 谷歌地圖創(chuàng)始人拉斯離開谷歌加盟 Facebook
4 谷歌地圖之父跳槽 Facebook 與 Wave 項目取消有關(guān)
5 谷歌地圖之父拉斯加盟社交網(wǎng)站 Facebook

對文檔進行分詞之后点楼,得到以下倒排索引

WordId Word DocIds
1 谷歌 1,2,3,4,5
2 地圖 1,2,3,4,5
3 之父 1,2,4,5
4 跳槽 1,4
5 Facebook 1,2,3,4,5
6 加盟 2,3,5
7 創(chuàng)始人 3
8 拉斯 3,5
9 離開 3
10 4
.. .. ..

另外白对,實用的倒排索引還可以記錄更多的信息掠廓,比如文檔頻率信息,表示在文檔集合中有多少個文檔包含某個單詞甩恼。

那么蟀瞧,有了倒排索引沉颂,搜索引擎可以很方便地響應(yīng)用戶的查詢。比如用戶輸入查詢 Facebook悦污,搜索系統(tǒng)查找倒排索引铸屉,從中讀出包含這個單詞的文檔,這些文檔就是提供給用戶的搜索結(jié)果切端。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彻坛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子踏枣,更是在濱河造成了極大的恐慌昌屉,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椰于,死亡現(xiàn)場離奇詭異怠益,居然都是意外死亡,警方通過查閱死者的電腦和手機瘾婿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門蜻牢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人偏陪,你說我怎么就攤上這事抢呆。” “怎么了笛谦?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵抱虐,是天一觀的道長。 經(jīng)常有香客問我饥脑,道長恳邀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任灶轰,我火速辦了婚禮谣沸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笋颤。我一直安慰自己乳附,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布伴澄。 她就那樣靜靜地躺著赋除,像睡著了一般。 火紅的嫁衣襯著肌膚如雪非凌。 梳的紋絲不亂的頭發(fā)上举农,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音敞嗡,去河邊找鬼颁糟。 笑死祭犯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的滚停。 我是一名探鬼主播沃粗,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼键畴!你這毒婦竟也來了最盅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤起惕,失蹤者是張志新(化名)和其女友劉穎涡贱,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惹想,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡问词,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘀粱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片激挪。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锋叨,靈堂內(nèi)的尸體忽然破棺而出垄分,到底是詐尸還是另有隱情,我是刑警寧澤娃磺,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布薄湿,位于F島的核電站,受9級特大地震影響偷卧,放射性物質(zhì)發(fā)生泄漏豺瘤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一听诸、第九天 我趴在偏房一處隱蔽的房頂上張望坐求。 院中可真熱鬧,春花似錦蛇更、人聲如沸瞻赶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至璧南,卻和暖如春掌逛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背司倚。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工豆混, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留篓像,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓皿伺,卻偏偏與公主長得像员辩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鸵鸥,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容