上篇文章提到過,在elasticsearch和磁盤之間還有一層cache也就是filesystem cache,大部分新增或者修改,刪除的數據都在這層cache中,若是沒有flush操做,那麼就不能100%保證系統的數據不會丟失,好比忽然斷電或者機器宕機了,但實際狀況是es中默認是30分鐘才flush一次磁盤,這麼長的時間內,若是發生不可控的故障,那麼是否是一定會丟失數據呢?api
很顯然es的設計者早就考慮了這個問題,在兩次full commit操做(flush)之間,若是發生故障也不能丟失數據,那麼es是如何作到的呢?異步
在es裏面引入了transaction log(簡稱translog),這個log的做用就是每條數據的任何操做都會被記錄到該log中,很是像Hadoop裏面的edits log和hbase裏面的WAL log,以下圖: async
transaction log的工做流程以下:elasticsearch
(1)當一個文檔被索引時,它會被添加到內存buffer裏面同時也會在translog裏面追加oop
(2)當每一個shard每秒執行一次refresh操做完畢後,內存buffer會被清空但translog不會。性能
過程以下:大數據
2.1 當refresh動做執行完畢後,內存buffer裏面的數據會被寫入到一個segment裏面,這個還在cache中,並無執行flush命令 2.2 新生成的segment在cache中,會被打開,這個時候就能夠搜索新加的數據 2.3 最後內存buffer裏面的數據會被清空
上面過程以下圖: 優化
(3)隨着更多的document添加,內存buffer區會不斷的refresh,而後clear,但translog數量卻越增越多,以下圖:設計
(4)當達到默認的30分鐘時候,translog也會變得很是大,這個時候index要執行一次flush操做,同時會生成一個新的translog文件,而且要執行full commit操做,流程以下:3d
4.1 內存buffer裏的全部document會被生成一個新的segment 4.2 而後segment被refresh到系統cache後,內存buffer會被清空 4.3 接着commit point會被寫入到磁盤上 4.4 filesystem cache會被flush到磁盤上經過fsync操做 4.5 最後舊的translog會被刪除,並會生成一個新的translog
以下圖:
tanslog的做用就是給全部尚未flush到硬盤上的數據提供持久化記錄,當es重啓時,它首先會根據上一次中止時的commit point文件把全部已知的segments文件給恢復出來,而後再經過translog文件把上一次commit point以後的全部索引變化包括添加,刪除,更新等操做給重放出來。
除此以外tanslog文件還用於提供一個近實時的CURD操做,當咱們經過id讀取,更新或者刪除document時,es在從相關的segments裏面查詢document以前,es會首先從translog裏面獲取最近的變化,這樣就意味着es老是近實時的優先訪問最新版本的數據。
咱們知道執行flush命令以後,全部系統cache中的數據會被同步到磁盤上而且會刪除舊的translog而後生成新的translog,默認狀況下es的shard會每隔30分鐘自動執行一次flush命令,或者當translog變大超過必定的閾值後。
flush命令的api以下:
POST /blogs/_flush //flush特定的index POST /_flush?wait_for_ongoing//flush全部的index知道操做完成以後返回響應
flush命令基本不須要咱們手動操做,但當咱們要重啓節點或者關閉索引時,最好提早執行如下flush命令做爲優化,由於es恢復索引或者從新打開索引時,它必需要先把translog裏面的全部操做給恢復,因此也就是說translog越小,recovery恢復操做就越快。
咱們知道了tangslog的目的是確保操做記錄不丟失,那麼問題就來了,tangslog有多可靠?
默認狀況下,translog會每隔5秒或者在一個寫請求(index,delete,update,bulk)完成以後執行一次fsync操做,這個進程會在全部的主shard和副本shard上執行。 這個守護進程的操做在客戶端是不會收到200 ok的請求。
在每一個請求完成以後執行一次translog的fsync操做仍是比較耗時的,雖然數據量可能比並非很大。 默認的es的translog的配置以下:
"index.translog.durability": "request"
若是在一個大數據量的集羣中數據並非很重要,那麼就能夠設置成每隔5秒進行異步fsync操做translog,配置以下:
PUT /my_index/_settings { "index.translog.durability": "async", "index.translog.sync_interval": "5s" }
上面的配置能夠在每一個index中設置,而且隨時均可以動態請求生效,因此若是咱們的數據相對來講並非很重要的時候,咱們開啓異步刷新translog這個操做,這樣性能可能會更好,但壞的狀況下可能會丟失5秒以內的數據,因此在設置以前要考慮清楚業務的重要性。
若是不知道怎麼用,那麼就用es默認的配置就行,在每次請求以後就執行translog的fsycn操做從而避免數據丟失。