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é)調節(jié)點)。
coordinating node 對 document 進行路由括享,將請求轉發(fā)給對應的 node(有 primary shard)搂根。
實際的 node 上的 primary shard 處理請求,然后將數(shù)據(jù)同步到 replica node铃辖。
coordinating node 如果發(fā)現(xiàn) primary node 和所有 replica node 都搞定之后剩愧,就返回響
應結果給客戶端。

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

可以通過 doc id 來查詢娇斩,會根據(jù) doc id 進行 hash仁卷,判斷出來當時把 doc id 分配到了哪個 shard上面去,從那個 shard 去查詢成洗。

????????????客戶端發(fā)送請求到任意一個 node五督,成為 coordinate node。

???????????? coordinate node 對 doc id 進行哈希路由瓶殃,將請求轉發(fā)到對應的 node充包,此時會使用 round-robin 隨機輪詢算法,在 primary shard 以及其所有 replica 中隨機選擇一個遥椿,讓讀請求負載均衡基矮。

????????????接收請求的 node 返回 document 給 coordinate node。

????????????coordinate node 返回 document 給客戶端冠场。

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

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

java 真好玩兒啊

java 好難學啊

j2ee 特別牛

你根據(jù) java 關鍵詞來搜索,將包含 java 的 document 給搜索出來碴裙。es 就會給你返回:java 真好玩兒啊钢悲,java 好難學啊点额。

? ????????????客戶端發(fā)送請求到一個 coordinate node。

????????????? 協(xié)調節(jié)點將搜索請求轉發(fā)到所有的 shard 對應的 primary shard 或 replica shard莺琳,都可以还棱。

? ????????????query phase:每個 shard 將自己的搜索結果(其實就是一些 doc id)返回給協(xié)調節(jié)點,由協(xié)調節(jié)點進行數(shù)據(jù)的合并惭等、排序珍手、分頁等操作,產出最終結果辞做。

? ????????????fetch phase:接著由協(xié)調節(jié)點根據(jù) doc id 去各個節(jié)點上拉取實際的 document 數(shù)據(jù)琳要,最終返回給客戶端。

寫請求是寫入 primary shard秤茅,然后同步給所有的 replica shard稚补;讀請求可以從 primary shard 或 replica shard 讀取,采用的是隨機輪詢算法框喳。

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


先寫入內存 buffer孔厉,在 buffer 里的時候數(shù)據(jù)是搜索不到的;同時將數(shù)據(jù)寫入 translog 日志文件帖努。

如果 buffer 快滿了撰豺,或者到一定時間,就會將內存 buffer 數(shù)據(jù) refresh 到一個新的 segmentfile 中拼余,但是此時數(shù)據(jù)不是直接進入 segment file 磁盤文件污桦,而是先進入 os cache 。這個過程就是 refresh匙监。

每隔 1 秒鐘凡橱,es 將 buffer 中的數(shù)據(jù)寫入一個新的 segment file,每秒鐘會產生一個新的磁盤文件 segment file亭姥,這個 segment file 中就存儲最近 1 秒內 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)級別的一個內存緩存中去狱从。只要 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)持久化到磁盤去一份了附帽。

重復上面的步驟埠戳,新的數(shù)據(jù)不斷進入 buffer 和 translog,不斷將 buffer 數(shù)據(jù)寫入一個又一個新的 segment file 中去蕉扮,每次 refresh 完 buffer 清空整胃,translog 保留。隨著這個過程推進喳钟,translog會變得越來越大屁使。當 translog 達到一定長度的時候,就會觸發(fā) commit 操作奔则。

commit 操作發(fā)生第一步蛮寂,就是將 buffer 中現(xiàn)有數(shù)據(jù) refresh 到 os cache 中去,清空 buffer易茬。然后酬蹋,將一個 commit point 寫入磁盤文件,里面標識著這個 commit point 對應的所有 segment file抽莱,同時強行將 os cache 中目前所有的數(shù)據(jù)都 fsync 到磁盤文件中去除嘹。最后清空 現(xiàn)有 translog 日志文件,重啟一個 translog岸蜗,此時 commit 操作完成尉咕。

這個 commit 操作叫做 flush。默認 30 分鐘自動執(zhí)行一次 flush璃岳,但如果 translog 過大年缎,也會觸發(fā) flush悔捶。flush 操作就對應著 commit 的全過程,我們可以通過 es api单芜,手動執(zhí)行 flush 操作蜕该,手動將 os cache 中的數(shù)據(jù) fsync 強刷到磁盤上去。

translog 日志文件的作用是什么洲鸠?你執(zhí)行 commit 操作之前堂淡,數(shù)據(jù)要么是停留在 buffer 中,要么是停留在 os cache 中扒腕,無論是 buffer 還是 os cache 都是內存绢淀,一旦這臺機器死了,內存中的數(shù)據(jù)就全丟了瘾腰。所以需要將數(shù)據(jù)對應的操作寫入一個專門的日志文件 translog 中皆的,一旦此時機器宕機,再次重啟的時候蹋盆,es 會自動讀取 translog 日志文件中的數(shù)據(jù)费薄,恢復到內存 buffer 和 os cache 中去。

translog 其實也是先寫入 os cache 的栖雾,默認每隔 5 秒刷一次到磁盤中去楞抡,所以默認情況下,可能有 5 秒的數(shù)據(jù)會僅僅停留在 buffer 或者 translog 文件的 os cache 中析藕,如果此時機器掛了拌倍,會丟失 5 秒鐘的數(shù)據(jù)。但是這樣性能比較好噪径,最多丟 5 秒的數(shù)據(jù)柱恤。也可以將 translog 設置成每次寫操作必須是直接 fsync 到磁盤,但是性能會差很多找爱。

實際上你在這里梗顺,如果面試官沒有問你 es 丟數(shù)據(jù)的問題,你可以在這里給面試官炫一把车摄,你說寺谤,其實 es第一是準實時的,數(shù)據(jù)寫入 1 秒后可以搜索到吮播;可能會丟失數(shù)據(jù)的变屁。有 5 秒的數(shù)據(jù),停留在 buffer意狠、translog os cache粟关、segment file os cache 中,而不在磁盤上环戈,此時如果宕機闷板,會導致 5 秒的數(shù)據(jù)丟失澎灸。

總結一下,數(shù)據(jù)先寫入內存 buffer遮晚,然后每隔 1s性昭,將數(shù)據(jù) refresh 到 os cache,到了 os cache 數(shù)據(jù)就能被搜索到(所以我們才說 es 從寫入到能被搜索到县遣,中間有 1s 的延遲)糜颠。每隔 5s,將數(shù)據(jù)寫入translog 文件(這樣如果機器宕機萧求,內存數(shù)據(jù)全沒民傻,最多會有 5s 的數(shù)據(jù)丟失)绷落,translog 大到一定程度左敌,或者默認每隔 30mins止潘,會觸發(fā) commit 操作搁拙,將緩沖區(qū)的數(shù)據(jù)都 flush 到 segment file 磁盤文件中秒梳。

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

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

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

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

buffer 每 refresh 一次,就會產生一個 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ù)結構。

倒排索引

在搜索引擎中哎媚,每個文檔都有一個對應的文檔 ID喇伯,文檔內容被表示為一系列關鍵詞的集合。例如拨与,文檔 1 經(jīng)過分詞稻据,提取了 20 個關鍵詞,每個關鍵詞都會記錄它在文檔中出現(xiàn)的次數(shù)和出現(xiàn)位置买喧。那么捻悯,倒排索引就是關鍵詞到文檔 ID 的映射,每個關鍵詞都對應著一系列的文件淤毛,這些文件中都出現(xiàn)了

關鍵詞今缚。

舉個栗子。

有以下文檔:


對文檔進行分詞之后低淡,得到以下倒排索引姓言。


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

那么猪杭,有了倒排索引兽泣,搜索引擎可以很方便地響應用戶的查詢。比如用戶輸入查詢 Facebook胁孙,搜索系統(tǒng)查找倒排索引唠倦,從中讀出包含這個單詞的文檔,這些文檔就是提供給用戶的搜索結果涮较。

要注意倒排索引的兩個重要細節(jié):

????????????1.倒排索引中的所有詞項對應一個或多個文檔稠鼻;

????????????2.倒排索引中的詞項根據(jù)字典順序升序排列

????????????上面只是一個簡單的栗子,并沒有嚴格按照字典順序升序排列狂票。


?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末候齿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慌盯,老刑警劉巖周霉,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亚皂,居然都是意外死亡俱箱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門灭必,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狞谱,“玉大人,你說我怎么就攤上這事禁漓「疲” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵播歼,是天一觀的道長伶跷。 經(jīng)常有香客問我,道長秘狞,這世上最難降的妖魔是什么叭莫? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮谒撼,結果婚禮上食寡,老公的妹妹穿的比我還像新娘雾狈。我一直安慰自己廓潜,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布善榛。 她就那樣靜靜地躺著辩蛋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪移盆。 梳的紋絲不亂的頭發(fā)上悼院,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音咒循,去河邊找鬼据途。 笑死,一個胖子當著我的面吹牛叙甸,可吹牛的內容都是我干的颖医。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼裆蒸,長吁一口氣:“原來是場噩夢啊……” “哼熔萧!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤佛致,失蹤者是張志新(化名)和其女友劉穎贮缕,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俺榆,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡感昼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肋演。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抑诸。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖爹殊,靈堂內的尸體忽然破棺而出蜕乡,到底是詐尸還是另有隱情,我是刑警寧澤梗夸,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布层玲,位于F島的核電站,受9級特大地震影響反症,放射性物質發(fā)生泄漏辛块。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一铅碍、第九天 我趴在偏房一處隱蔽的房頂上張望润绵。 院中可真熱鬧,春花似錦胞谈、人聲如沸尘盼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卿捎。三九已至,卻和暖如春径密,著一層夾襖步出監(jiān)牢的瞬間午阵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工享扔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留底桂,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓惧眠,卻偏偏與公主長得像籽懦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锉试,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容