ES讀寫數據的工作原理


es寫入數據的工作原理是什么啊?es查詢數據的工作原理是什么?底層的lucence介紹一下唄?倒排索引了解嗎?

一、es寫數據過程

1、客戶端選擇一個node發送請求過去,這個node就是coordinating node(協調節點)

2、coordinating node 對document進行路由,將請求轉發給對應的node(有primary shard)

3、實際的node上的primary shard 處理請求,然后將數據同步到replica node。

4、coordinating node如果發現 primary node和所有replica node都搞定之后,就返回響應結果給客戶端。

二、es讀數據過程

可以通過doc id 來查詢,會根據doc id進行hash,判斷出來當時把doc id分配到了哪個shard上面去,從那個shard去查詢。

1、客戶端發送請求到任意一個node,成為coordinate node

2、coordinate node 對doc id進行哈希路由,將請求轉發到對應node,此時會使用round-robin隨機輪詢算法,在primary shard 以及其所有replica中隨機選擇一個,讓讀請求負載均衡。

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

4、coordinate node返回document給客戶端。

三、es搜索數據過程

es最強大的是做全文檢索

1、客戶端發送請求到一個coordinate node。

2、協調節點將搜索請求轉發到所有的shard對應的primary shard 或 replica shard ,都可以。

3、query phase:每個shard將自己的搜索結果(其實就是一些doc id)返回給協調節點,由協調節點進行數據的合並、排序、分頁等操作,產出最終結果。

4、fetch phase:接着由協調節點根據doc id去各個節點上拉取實際的document數據,最終返回給客戶端。

寫請求是寫入primary shard,然后同步給所有的replica shard

讀請求可以從primary shard 或者 replica shard 讀取,采用的是隨機輪詢算法。

四、寫數據底層原理

1、先寫入內存buffer,在buffer里的時候數據是搜索不到的;同時將數據寫入translog日志文件。

如果buffer快滿了,或者到一定時間,就會將內存buffer數據refresh 到一個新的segment file中,但是此時數據不是直接進入segment file磁盤文件,而是先進入

os cache。這個過程就是 refresh。

每隔1秒鍾,es將buffer中的數據寫入一個新的segment file,每秒鍾會寫入一個新的segment file,這個segment file中就存儲最近1秒內 buffer中寫入的數據。

2、但是如果buffer里面此時沒有數據,那當然不會執行refresh操作,如果buffer里面有數據,默認1秒鍾執行一次refresh操作,刷入一個新的segment file中。

操作系統里面,磁盤文件其實都有一個東西,叫做os  cache,即操作系統緩存,就是說數據寫入磁盤文件之前,會先進入os  cache,先進入操作系統級別的

一個內存緩存中去。只要buffer中的數據被refresh 操作刷入os cache中,這個數據就可以被搜索到了。

3、為什么叫es是准實時的?NRT,全稱 near real-time。默認是每隔1秒refresh一次的,所以es是准實時的,因為寫入的數據1s之后才能被看到。

可以通過es的restful api或者 java api,手動執行一次 refresh操作,就是手動將buffer中的數據刷入os cache中,讓數據立馬就可以被搜索到。只要

數據被輸入os cache中,buffer 就會被清空了,因為不需要保留buffer了,數據在translog里面已經持久化到磁盤去一份了。

4、重復上面的步驟,新的數據不斷進入buffer和translog,不斷將buffer數據寫入一個又一個新的segment file中去,每次refresh完buffer清空,translog保留。

隨着這個過程的推進,translog會變得越來越大。當translog達到一定長度的時候,就會觸發commit操作。

5、commit操作發生的第一步,就是將buffer中現有的數據refresh到os  cache中去,清空buffer。然后將一個commit  point寫入磁盤文件,里面標識者這個commit

point 對應的所有segment file,同時強行將os cache中目前所有的數據都fsync到磁盤文件中去。最后清空現有 translog日志文件,重啟一個translog,此時commit操作完成。

6、這個commit操作叫做flush。默認30分鍾自動執行一次flush,但如果translog過大,也會觸發flush。flush操作就對應着commit的全過程,我們可以通過es api,手動執行

flush操作,手動將os  cache中數據fsync強刷到磁盤上去。

 

7、translog日志文件的作用是什么?

執行commit 操作之前,數據要么是停留在buffer中,要么是停留在os cache中,無論是buffer 還是os cache都是內存,一旦這台機器死了,內存中的數據就全丟了。

所以需要將數據對應的操作寫入一個專門的日志文件translog中,一旦此時機器宕機了,再次重啟的時候,es會自動讀取translog日志文件中的數據,恢復到內存buffer

和os cache中去。

8、translog其實也是先寫入os  cache的,默認每隔5秒刷一次到磁盤中去,所以默認情況下,可能有5s的數據會僅僅停留在buffer或者translog文件的os cache中,如果

此時機器掛了,會丟失5秒鍾的數據。但是這樣性能比較好,最多丟5秒的數據。

也可以將translog設置成每次寫操作必須是直接fsync到磁盤,但是性能會差很多。

9、es第一是准實時的,數據寫入1秒后就可以搜索到:可能會丟失數據的。有5秒的數據,停留在buffer、translog  os  cache 、segment file  os  cache中,而不在磁盤上,

此時如果宕機,會導致5秒的數據丟失。

10、總結::數據先寫入內存buffer,然后每隔1s,將數據refresh到 os cache,到了 os cache數據就能被搜索到(所以我們才說es從寫入到能被搜索到,中間有1s的延遲)。

每隔5s,將數據寫入到translog文件(這樣如果機器宕機,內存數據全沒,最多會有5s的數據丟失),translog達到一定程度,或者默認每隔30min,會觸發commit操作,將緩沖區的

數據都flush到segment file磁盤文件中。

數據寫入 segment file之后,同時就建立好了倒排索引。

 

五、刪除/更新數據底層原理

如果是刪除操作,commit的時候會生成一個 .del文件,里面將某個doc標識為 deleted狀態,那么搜索的時候根據 .del文件就知道這個doc是否被刪除了。

如果是更新操作,就是將原來的doc標識為deleted狀態,然后重新寫入一條數據。

buffer 每refresh一次,就會產生一個segment file,所以默認情況下是1秒鍾一個segment file,這樣下來segment file會越來越多,此時會定期執行merge。

每次merge的時候,會將多個segment file合並成一個,同時這里會將標識為 deleted的doc給物理刪除掉,然后將新的segment file寫入磁盤,這里會寫一個

commit point,標識所有新的 segment file,然后打開segment file供搜索使用,同時刪除舊的segment file。

 

六、底層lucence

簡單來說,lucence就是一個jar包,里面包含了封裝好的各種建立倒排索引的算法代碼。我們用java 開發的時候,引入 lucene  jar,然后基於lucene的api去開發

就可以了。

通過lucene,我們可以將已有的數據建立索引,lucene會在本地磁盤上面,給我們組織索引的數據結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM