Flink状态后端的使用

Flink提供了以下三种开箱即用的状态后端(用于存储状态数据),可以为所有flink作业配置相同的状态后端(flink-conf.yaml ),也可以为每个flink作业配置指定的状态后端。

  • MemoryStateBackend
  • FsStateBackend
  • RocksDBStateBackend

至于在实际应用中应该选择何种状态后端,需要结合业务场景及三种状态后端的特点以做出最佳选择,本文对三种状态后端的特点做了总结,如下:

  状态存储位置 是否支持异步快照 快照方式 状态大小 限制 适用场景

MemoryStateBackend

内存(jobmanager java堆上) 全量,不支持增量

很小,单个状态5M,可通过如下方式设置状态大小,第二个参数为关闭异步快照。

new MemoryStateBackend(MAX_MEM_STATE_SIZE, false)

1.单个状态限制不超过5M。

2.状态不能超过akka frame大小,见下。

3.聚合状态不能超过jobmanager内存。

本地开发与调试,持有很小的状态。

FsStateBackend

内存(状态存taskmanger内存,最小元数据存jobmanager内存)。 全量,不支持增量 大状态。 因内存限制,不适合超大状态。 大状态,长窗口。

RocksDBStateBackend

RocksDB(taskmanger 数据目录) 支持全量和增量 超大状态。 key,value最大不超过2^31字节,说明见下 超大状态,长窗口。
  • akka frame大小(默认10M):jobmanager和taskmanger之间传递的消息的最大限制。

  • RocksDBStateBackend说明:在状态值累加到最大值后,下次获取状态值将会失败,目前是RocksDB JNI的一个限制(官方说明见下)。此状态后端能够存储的状态数量仅仅受可用的磁盘空间限制,和FsStateBackend相比,吞吐量会稍低。因为从后端读/写状态对象时要进行序列化/反序列化。相比于存储于堆上的状态数据而言,代价要更加昂贵。

       IMPORTANT: states that use merge operations in RocksDB (e.g. ListState) can silently accumulate value sizes > 2^31 bytes and will then fail on their next retrieval. This is currently a limitation of RocksDB JNI.

如何配置使用状态后端?

默认不配置使用的是MemoryStateBackend状态后端,建议使用FsStatebackend或者RocksDBBackend。使用时构建一个状态后端实例并通过执行环境设置。如:

配置FsStatebackend:

val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
//fs状态后端配置,如为file:///,则在taskmanager的本地
val checkPointPath = new Path("hdfs:///flink/checkpoints") 
val fsStateBackend: StateBackend = new FsStateBackend(checkPointPath)
env.setStateBackend(fsStateBackend)

配置RocksDBBackend:

  private val checkpointDataUri = "hdfs:///flink/checkpoints"
  private val tmpDir = "file:///tmp/rocksdb/data/"
  val env = StreamExecutionEnvironment.getExecutionEnvironment
  val fsStateBackend: StateBackend = new FsStateBackend(checkpointDataUri)
  val rocksDBBackend: RocksDBStateBackend = new RocksDBStateBackend(fsStateBackend, TernaryBoolean.TRUE)
  val config = new Configuration()
  //TIMER分为HEAP(默认,性能更好)和RocksDB(扩展好)
 config.setString(RocksDBOptions.TIMER_SERVICE_FACTORY,RocksDBStateBackend.PriorityQueueStateType.ROCKSDB.toString)
  rocksDBBackend.configure(config)
  rocksDBBackend.setDbStoragePath(tmpDir)
  env.setStateBackend(rocksDBBackend.asInstanceOf[StateBackend])

官网还给出了可以根据需要自定义option:

RocksDBStateBackend.setOptions(new MyOptions());
public class MyOptions implements OptionsFactory {
    @Override
    public DBOptions createDBOptions() {
        return new DBOptions()
            .setIncreaseParallelism(4)
            .setUseFsync(false)
            .setDisableDataSync(true);
    }

    @Override
    public ColumnFamilyOptions createColumnOptions() {
        return new ColumnFamilyOptions()
            .setTableFormatConfig(
                new BlockBasedTableConfig()
                    .setBlockCacheSize(256 * 1024 * 1024)  // 256 MB
                    .setBlockSize(128 * 1024));            // 128 KB
    }
}

觉得太麻烦?flink提供了预定义选项供使用:

RocksDBStateBacked.setPredefinedOptions(PredefinedOptions.SPINNING_DISK_OPTIMIZED_HIGH_MEM)

另外,在flink1.6版本中使用状态后端需要注意:

一.本地恢复限制
Limitation: Currently, task-local recovery only covers keyed state backends.
Keyed state is typically by far the largest part of the state.In the near future,
we will also cover operator state and timers.
目前的1.6版本中支持状态本地恢复的只有keyed state,还不支持operator state。
二.增量检查点限制
RocksDBStateBackend is currently the only backend that offers incremental checkpoints.
RocksDB是唯一支持增量检查点的backend。也就意味着MemoryStateBackend和FsStateBackend进行checkpoint时的状态是全量数据。
三.RocksDB Timers限制
The combination RocksDB state backend / with incremental checkpoint / with heap-based timers currently does NOT
support asynchronous snapshots for the timers state. Other state like keyed state is still snapshotted
asynchronously. Please note that this is not a regression from previous versions and will be resolved with
FLINK-10026.
组合RocksDB state backend / with incremental checkpoint / with heap-based timers不支持timers state异步快照。此
情况将在FLINK-10026进行解决。

你可能感兴趣的:(Flink技术研究与应用)