Elasticsearch 如何保證寫入過程中不丟失資料的

蓝胖子的编程梦發表於2024-03-12

丟失資料的本質

在本文開始前,首先明白一個點,平時我們說的元件資料不丟失究竟是在指什麼,如果你往ES寫入資料,ES返回給你寫入錯誤,這個不算資料丟失。如果你往ES寫入資料,ES返回給你成功,但是後續因為ES節點重啟或當機導致寫入的資料不見了,這個才叫資料丟失。

簡而言之,丟失資料的本質是ES本身搞丟了返回結果是成功寫入的資料

資料寫入流程

image.png

1,寫入時,ES會首先往一塊記憶體快取中寫入資料,這快記憶體快取在ES中叫index buffer,此時資料是不可見的,只有經過refresh操作後,資料才能變得可見。

index buffer的大小設定可以透過 下面的請求去進行設定,如下,設定了index buffer的大小為總記憶體的30%

PUT /_cluster/settings
{
   "persistent" : {
       "indices.memory.index_buffer_size" : "30%"  
   }
}

2, 在寫入index buffer成功後,會寫translog 記錄寫入的資料。此時資料依然不可見。由於作業系統對檔案寫入,並不會立即落盤。所以ES提供了關於刷盤的配置,index.translog.durability兩個選項值,如下,

  • request 會在每次建立segment寫入資料後就對translog進行刷盤操作。
  • async 則會定時對translog進行刷盤操作。定時重新整理到磁碟的週期是透過index.translog.sync_interval 引數去進行控制,預設是5s。

3,refresh 操作可以主動觸發也可以定時觸發,預設是1s會進行一次, 該操作會建立一個lucece的segment段用於儲存新寫入到index buffer中的資料,注意這裡即使寫入到了segment裡,資料還是在os Cache系統檔案系統快取中,並沒有落入磁碟,只有 在lucece將資料 commit 到磁碟後,資料才能落盤。

4, 在檔案系統快取中的segment總歸還是要寫入磁碟,預設每30分鐘,或者當translog的日誌量達到某個量級時,segment會進行落盤,同時刪掉translog日誌。這個量級由index.translog.flush_threshold_size 去進行控制,預設是512mb。

在瞭解了ES的寫入資料的過程後,我們可以發現,如果將index.translog.durability 設定為request ,這樣便能讓每次請求返回客戶端成功時,保證一定會有translog日誌儲存到磁碟上,後續如果在系統快取中的segment因為系統當機而沒有落盤依然能夠透過translog去進行恢復。

而如果index.translog.durability 設定為 async 則有可能會丟失5s的資料。

相關文章