状态后端
数据流API的程序中通常以如下几种形式保存状态:
窗口算子收集数据元素或聚合直到他们被发射出去
转换函数会使用key/value状态接口存储数据
转换函数会实现CheckpointedFunction接口,来保证局部变量的故障恢复
当检查点机制被激活,这种状态在检查点上保持,以防止数据丢失和一致地恢复。
状态是如何在内部表示,并且它如何在检查点上保持依赖于选择的状态后端。
可用的状态后端
开箱即用,flink直接提供了如下的状态后端:
MemoryStateBackend
FsStateBackend
RocksDBStateBackend
在没有任何配置时,系统使用MemoryStateBackend
MemoryStateBackend
MemoryStateBackend将数据以对象的方式保存在java虚拟机的堆中。key/value状态和窗口算子保持hash表存储值和触发器,等等。
检查点时,状态后端会快照状态并将快照作为ack消息发送给jobmanager(主),通过将数据保存在堆上。
MemoryStateBackend能够配置使用异步快照。虽然强烈鼓励使用异步快照来避免阻塞管道,但需要注意,当前默认情况下就启动了此功能。
可以在构造MemoryStateBackend实例时指定false标志来关闭这个特性,例如:
new MemoryStateBackend(MAX_MEM_STATE_SIZE, false);
MemoryStateBackend的局限性:
每个独立的状态默认限制大小为5m。可以在构造MemoryStateBackend时增加限制大小。
不考虑配置的最大状态尺寸,状态不能超过akka框架的尺寸。
聚合状态必须写入JobManager内存。
MemoryStateBackend适用的场景:
本地部署和调试
作业保持小规模的状态,例如作业由每次处理一条记录的算子组成(map,flatmap,filter,…).
kafka消费需要非常小的状态。
FsStateBackend
FsStateBackend配置文件系统URL路径(type,address,path),例如:“hdfs://namenode:40010/flink/checkpoints”或者“file:///data/flink/checkpoints”
FsStateBackend保存in-flight数据在TaskManager内存中.生成checkpoint时,它将状态快照写入配置的文件系统目录。
极小的元数据存储在JobManager内存中(或者在高可靠性模式下存储在元数据检查点)
FsStateBackend默认使用异步快照来避免写入状态检查点会阻塞数据流处理。
取消这个默认特性,可以在构造FsStateBackend时指定false标志,例如:
new FsStateBackend(path, false);
FsStateBackend适用的场景:
任务使用大的状态,大的窗口,大的key/value状态
需要高可靠性
RocksDBStateBackend
RocksDBStateBackend配置文件系统URl路径,例如:“hdfs://namenode:40010/flink/checkpoints”或“file:///data/flink/checkpoints”
RocksDBStateBackend保存in-flight数据在TaskManager数据目录下的RocksDB数据库中。
生成检查点时,完整的RocksDB数据库会被作为检查点保存在配置的文件系统目录下。
极少的元数据存储在JobManager内存中(或者在高可靠性模式下存储在元数据检查点)
RocksDBStateBackend总是执行异步快照。
RocksDBStateBackend的限制:
由于RocksDB的JNI API基于byte[],单个key和value最大支持的尺寸为2^31 bytes。
重要:带有合并操作的状态(例如:liststate)在RocksDB可能会悄然累计超过2^31 bytes,这会导致取回状态时发生失败。
这时目前RocksDB JNI的限制。
RocksDBStateBackend适用的场景:
任务使用非常大的状态,大的窗口,大的key/value状态
需要高可靠性
注意状态的规模限制取决于可用的硬盘大小。相对FsStateBackend将状态保存在内存,RocksDBStateBackend允许保存非常大的状态。
但这也意味着,它实现的最大吞吐量更低。对后端的读取/写入操作必须经过序列化/反序列化才能检索/存储这些状态对象,相对与基于堆
实现的后端耗费了更多的性能。
RocksDBStateBackend是当前唯一提供增量检查点的后端。
某些RocksDB提供可用的原生度量但没有默认打开,可以查阅完整的文档。
配置一个状态后端
默认的状态后端,没有任何配置下就是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
state.checkpoints.dir选项定义所有后端写入检查点数据和元数据文件的路径。可以查看更多关于检查点目录结构的细节。
配置文件的一段节选:
#The backend that will be used to store operator state checkpoints
state.backend: filesystem
#Directory for storing checkpoints
state.checkpoints.dir: hdfs://namenode:40010/flink/checkpoints
RocksDB状态后端的配置选项
key 默认值 描述
state.backend.rocksdb.localdir none 保存RocksDB文件的本地路径(TaskManager上)
state.backend.rocksdb.timer-service.factory HEAP 这决定了定时器服务状态实现的工厂。可选堆(基于堆,默认值)或者ROCKSDB基于ROCKSDB的实现。