原文連結: 一文了解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的狀態後端