寫數據底層原理:
1)先寫入buffer,在buffer里的時候數據是搜索不到的;同時將數據寫入translog日志文件
2)
如果buffer快滿了,或者到一定時間,就會將buffer數據refresh到一個新的segment file中,
但是此時數據不是直接進入segment file的磁盤文件的,而是先進入os cache的。
這個過程就是refresh。
每隔1秒鍾,es將buffer中的數據寫入一個新的segment file,每秒鍾會產生一個新的磁盤文件,segment file,這個segment file中就存儲最近1秒內buffer中寫入的數據。
但是如果buffer里面此時沒有數據,那當然不會執行refresh操作咯,
如果buffer里面有數據,默認1秒鍾執行一次refresh操作,刷入一個新的segment file中。
操作系統里面,磁盤文件其實都有一個東西,叫做os cache,操作系統緩存,就是說數據寫入磁盤文件之前,會先進入os cache,先進入操作系統級別的一個內存緩存中去
只要buffer中的數據被refresh操作,刷入os cache中,就代表這個數據就可以被搜索到了。
為什么叫es是准實時的?NRT,near real-time,准實時。默認是每隔1秒refresh一次的,所以es是准實時的,因為寫入的數據1秒之后才能被看到。
可以通過es的restful api或者java api,手動執行一次refresh操作,就是手動將buffer中的數據刷入os cache中,讓數據立馬就可以被搜索到。
只要數據被輸入os cache中,buffer就會被清空了,因為不需要保留buffer了,數據在translog里面已經持久化到磁盤去一份了。
3)只要數據進入os cache,此時就可以讓這個segment file的數據對外提供搜索了
4)重復1~3步驟,新的數據不斷進入buffer和translog,不斷將buffer數據寫入一個又一個新的segment file中去,每次refresh完buffer清空,translog保留。隨着這個過程推進,translog會變得越來越大。當translog達到一定長度的時候,就會觸發commit操作。
buffer中的數據,倒是好,每隔1秒就被刷到os cache中去,然后這個buffer就被清空了。所以說這個buffer的數據始終是可以保持住不會填滿es進程的內存的。
每次一條數據寫入buffer,同時會寫入一條日志到translog日志文件中去,所以這個translog日志文件是不斷變大的,當translog日志文件大到一定程度的時候,就會執行commit操作。
5)commit操作發生第一步,就是將buffer中現有數據refresh到os cache中去,清空buffer
6)將一個commit point寫入磁盤文件,里面標識着這個commit point對應的所有segment file
7)強行將os cache中目前所有的數據都fsync到磁盤文件中去
translog日志文件的作用是什么?就是在你執行commit操作之前,數據要么是停留在buffer中,要么是停留在os cache中,無論是buffer還是os cache都是內存,一旦這台機器死了,內存中的數據就全丟了。
所以需要將數據對應的操作寫入一個專門的日志文件,translog日志文件中,一旦此時機器宕機,再次重啟的時候,es會自動讀取translog日志文件中的數據,恢復到內存buffer和os cache中去。
commit操作:1、寫commit point;2、將os cache數據fsync強刷到磁盤上去;3、清空translog日志文件
8)將現有的translog清空,然后再次重啟啟用一個translog,此時commit操作完成。默認每隔30分鍾會自動執行一次commit,但是如果translog過大,也會觸發commit。整個commit的過程,叫做flush操作。我們可以手動執行flush操作,就是將所有os cache數據刷到磁盤文件中去。
不叫做commit操作,叫flush操作。es中的flush操作,就對應着commit的全過程。我們也可以通過es api,手動執行flush操作,手動將os cache中的數據fsync強刷到磁盤上去,記錄一個commit point,清空translog日志文件。
9)translog其實也是先寫入os cache的,默認每隔5秒刷一次到磁盤中去,所以默認情況下,可能有5秒的數據會僅僅停留在buffer或者translog文件的os cache中,如果此時機器掛了,會丟失5秒鍾的數據。但是這樣性能比較好,最多丟5秒的數據。也可以將translog設置成每次寫操作必須是直接fsync到磁盤,但是性能會差很多。
es第一是准實時的,數據寫入1秒后可以搜索到;可能會丟失數據的,你的數據有5秒的數據,停留在buffer、translog os cache、segment file os cache中,有5秒的數據不在磁盤上,此時如果宕機,會導致5秒的數據丟失。
如果你希望一定不能丟失數據的話,你可以設置個參數,官方文檔,百度一下。每次寫入一條數據,都是寫入buffer,同時寫入磁盤上的translog,但是這會導致寫性能、寫入吞吐量會下降一個數量級。本來一秒鍾可以寫2000條,現在你一秒鍾只能寫200條,都有可能。
10)如果是刪除操作,commit的時候會生成一個.del文件,里面將某個doc標識為deleted狀態,那么搜索的時候根據.del文件就知道這個doc被刪除了
11)如果是更新操作,就是將原來的doc標識為deleted狀態,然后新寫入一條數據
12)buffer每次refresh一次,就會產生一個segment file,所以默認情況下是1秒鍾一個segment file,segment file會越來越多,此時會定期執行merge
13)每次merge的時候,會將多個segment file合並成一個,同時這里會將標識為deleted的doc給物理刪除掉,然后將新的segment file寫入磁盤,這里會寫一個commit point,標識所有新的segment file,然后打開segment file供搜索使用,同時刪除舊的segment file。
es里的寫流程,有4個底層的核心概念,refresh、flush、translog、merge
當segment file多到一定程度的時候,es就會自動觸發merge操作,將多個segment file給merge成一個segment file。