一文了解Flink State Backends

MindForward發表於2022-01-11

原文連結: 一文了解Flink State Backends

當我們使用Flink進行流式計算時,通常會產生各種形式的中間結果,我們稱之為State。有狀態產生,就必然涉及到狀態的儲存,那麼Flink中定義了哪些形式的狀態儲存呢,下面一一給大家介紹一下。

State Backends

  • MemoryStateBackend
  • FsStateBackend
  • RocksDBStateBackend

MemoryStateBackend

顧名思義,MemoryStateBackend狀態後端是將狀態資料以Object的形式存放於Java Heap中。

當執行檢查點時,MemoryStateBackend會為當前的狀態生成snapshot,然後將快照資訊作為檢查點ack訊息的一部分傳送給JobManager(master節點),JobManager會將收到的快照資料存放於自己的堆記憶體中。

MemoryStateBackend預設採用非同步snapshots的方式來避免資料流管道阻塞,這是一種比較推薦的方式。當然,我們也可以通過配置來禁用這種方式。

new MemoryStateBackend(MAX_MEM_STATE_SIZE, false); // MAX_MEM_STATE_SIZE表示最大允許的狀態容量

MemoryStateBackend的使用限制

  • 每個狀態的大小預設限制為5MB,可以通過建構函式設定狀態大小
  • 不管如何配置最大狀態大小,都不能超過akka幀大小
  • 聚合狀態大小必須合乎JobManager的記憶體大小

基於以上這些限制,我們通常建議在如下場景中使用MemoryStateBackend:

  • 本地開發除錯
  • 無狀態作業或者儲存少量狀態的作業

此外,官方建議將託管記憶體(Managed Memory)設定為0,這樣可以確保為JVM上的使用者程式分配最大的記憶體。

FsStateBackend

FsStateBackend需要配置一個檔案系統URL,如:“hdfs://namenode:40010/flink/checkpoints” or “file:///data/flink/checkpoints”。
FsStateBackend將作業執行過程中的動態資料存放在TaskManager的記憶體當中,當執行檢查點時,狀態快照資料會被儲存在配置的檔案系統目錄中,還有一部分metadata資料會被儲存在JobManager的記憶體當中。

同樣的,FsStateBackend也是預設採用非同步snapshot的方式。我們可以通過例項化FsStateBackend來更改快照生成方式。

 new FsStateBackend(path, false);

官方建議在以下場景中使用FsStateBackend:

  • 作業中包含大狀態、長視窗以及大鍵值狀態
  • 高可用應用場景

同樣官方建議將託管記憶體(Managed Memory)設定為0,這樣可以確保為JVM上的使用者程式分配最大的記憶體。

RocksDBStateBackend

RocksDBStateBackend同樣需要配置一個檔案系統URL:“hdfs://namenode:40010/flink/checkpoints” or “file:///data/flink/checkpoints”。

RocksDBStateBackend將作業執行過程中的動態資料存放在RocksDB資料庫中,RocksDB資料庫預設儲存在TaskManager的資料目錄下。當執行檢查點時,整個RocksDB資料庫會被存檔到配置的檔案系統目錄下。只有少量的metadata資料儲存在JobManager的記憶體當中。

同樣地,RocksDBStateBackend通常也採用非同步snapshot的方式。

使用上的一些限制:

  • 由於RocksDB的JNI bridge API是基於byte[]的,因此可支援的最大key值大小是2^31 byte。這個限制一般情況下不會有問題,但當作業中的狀態是基於不斷地merge操作生成時,很容易超過這個大小限制,這個時候就會出現檢索失敗的錯誤。

官方建議在以下場景中使用RocksDBStateBackend:

  • 作業中包含大狀態、長視窗以及大鍵值狀態
  • 高可用應用場景

乍一看,好像跟FsStateBackend沒啥區別?其實不是,這裡需要注意的是,當我們使用RocksDBStateBackend作為狀態儲存時,可以維護的狀態大小僅僅受限於程式可訪問的磁碟空間大小。這就使得我們可以維護比FsStateBackend更大的作業狀態。

當然,這也帶來一個問題:由於與狀態後端之間的所有讀寫操作都要經過de-/serialization,因此這種方式犧牲了一定的吞吐量。

總結

  • MemoryStateBackend、FsStateBackend都是基於堆的狀態儲存
  • RocksDBStateBackend是目前唯一的一種支援增量checkpoint的狀態後端

相關文章