­

一文了解Flink State Backends

原文鏈接: 一文了解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的狀態後端
Tags: