使用Data Stream API編寫的程序通常以不同的形式持有狀態:
- 在窗口中收集或聚合元素,直到觸發狀態存儲
- 轉換函數可能使用key/value狀態接口來存儲元素
- 轉換函數可能實現
CheckpointedFunction
接口來使得它們的本地變量容錯。
參見流API指南中的狀態部分
當checkpoint被激活時,狀態會被持久化到checkpoint,以防止數據丟失和無縫恢復。狀態在內部如何組織和它們如何以及在哪持久化,依賴于所選的狀態后端。
可選的狀態后端
Flink內部提供了這些狀態后端:
- MemoryStateBackend
- FsStateBackend
- RocksDBStateBackend
如果沒有其他配置,系統將使用MemoryStateBackend。
MemoryStateBackend
MemoryStateBackend將內部的數據保存在Java堆上。 Key/value狀態和窗口操作符持有存儲值,觸發器等的哈希表。
當進行checkpoint時,這個狀態后端會對當前的狀態進行快照,并且將其作為checkpoint ACK消息的一部分發送給JobManager(master),該JobManager將其存儲在它的堆上。
MemoryStateBackend可以配置使用異步快照的方式。雖然我們強烈鼓勵使用異步快照的方式來避免管道阻塞,但是請注意,這個是一個新特性,目前默認情況下不啟用。為了啟用這個狀態,用戶可以在初始化 MemoryStateBackend
時將構造函數中相應的布爾標識設為 true
,例如:
new MemoryStateBackend(MAX_MEM_STATE_SIZE, true);
MemoryStateBackend的局限性:
- 單個狀態的大小默認情況下最大為5MB。這個值可以通過MemoryStateBackend構造函數進行增加。
- 無論配置的最大狀態大小為多少,狀態的大小不能超過akka幀大小(見Configuration)
- 聚合的狀態必須在JobManager的內存中能存放
MemoryStateBackend適用于:
- 本地開發和調試
- 只有很小狀態的作業,例如作業只由record-at-a-time函數組成(Map,FlatMap,Filter,...)。Kafka消費者只需要非常小的狀態。
FsStateBackend
FsStateBackend使用文件系統URL(類型,地址,路徑),例如“hdfs://namenode:40010/flink/checkpoints” 或 “file:///data/flink/checkpoints”.
FsStateBackend將in-flight數據存放在TaskManager的內存中。當進行checkpoint時,它將狀態快照寫入到配置的文件系統和目錄。最小的元數據存儲在JobManager的內存中(或者,在高可用模式下,在元數據checkpoint中)。
FsStateBackend默認使用異步快照以避免在寫狀態checkpoint時阻塞處理管道。要禁用此特性,用戶可以初始化 MemoryStateBackend
時將構造函數中相應的布爾標識設為 false
,例如:
new FsStateBackend(path, false);
FsStateBackend適用于:
- 具有大狀態,長窗口,大key/value狀態的作業
- 所有的高可用性設置
RocksDBStateBackend
RocksDBStateBackend 使用文件系統URL(類型,地址,路徑),例如“hdfs://namenode:40010/flink/checkpoints” 或 “file:///data/flink/checkpoints”.
RocksDBStateBackend將in-flight數據存儲在RocksDB數據庫中,它(默認)存儲在TaskManager的data目錄下。當checkpoint時,整個RocksDB數據庫將被checkpoint到配置的文件系統和目錄下。最小的元數據存儲在JobManager的內存中(或者,在高可用模式下,在元數據checkpoint中)。
RocksDBStateBackend總是執行異步快照。
RocksDBStateBackend的限制:
- 作為RocksDB的JNI橋接API是基于byte[]的,每個key和value的最大的支持大小是 2^31字節。重要:在RocksDB中使用合并操作的狀態(例如,ListState)能夠默默的積累到值的size大于 2^31字節,并且在下次檢索時會失敗。這是目前 RocksDB JNI的限制。
RocksDBStateBackend適用于:
- 具有大狀態,長窗口,大key/value狀態的作業
- 所有的高可用性設置
注意:你可以保持的狀態的數量只受限于磁盤可用空間的大小。相比于將狀態保存到內存的FsStateBackend,這允許保持非常大的狀態。然而,這也意味著,可以達到的最大的吞吐量會比狀態后端的吞吐量要低。
RocksDBStateBackend是目前唯一提供增量checkpoint的狀態后端(請參閱此處) 。
配置狀態后端
如果您不做任何指定,默認的狀態后端是JobManager。如果你希望為你的集群中的所有作業創建一個非默認的狀態后端,你可以通過在flink-conf.yaml中指定一個新的默認后端。默認的狀態后端可以在每個作業的基礎上進行覆蓋,如下所示.
設置一個作業級的狀態后端
作業的狀態后端通過作業中的 StreamExecutionEnvironment
進行設置,如下述示例所示:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStateBackend(new FsStateBackend("hdfs://namenode:40010/flink/checkpoints"));
設置默認狀態后端
默認狀態后端可以通過在 flink-conf.yaml
中設置state.backend
值指定。
可能的配置項是jobmanager (MemoryStateBackend), filesystem (FsStateBackend), rocksdb (RocksDBStateBackend),或者實現了狀態后端工廠FsStateBackendFactory的類的完全限定類名,例如,為RocksDBStateBackend設置為org.apache.flink.contrib.streaming.state.RocksDBStateBackendFactory
。
配置文件中的示例部分如下所示:
# The backend that will be used to store operator state checkpoints
state.backend: filesystem
# Directory for storing checkpoints
state.backend.fs.checkpointdir: hdfs://namenode:40010/flink/checkpoints