第1章 有状态的流计算

State(状态)是流式应用中普遍存在的一种对象,在流计算整个过程中,算子会不断的对状态进行读取和更新。在Flink当中既有内置的状态,也支持用户自定义状态。算子计算结果保存在state当中,下一笔数据到来时采用上一次计算结果和本次数据一起进行计算。而Flink流计算的状态数据是以state形式存在state backends中。

flink 获取算子 id flink 算子状态_流计算

在Flink当中,提及State与Checkpoint和Savepoint息息相关,它们产生的快照的数据就来源于各个算子产生的State。(Checkpoint和Savepoint在后续文章中详细说明)。

常见的State使用有:

  • Window窗口计算;
  • 计算时中间结果的实时读写;
  • 数据源读取进度,对数据源source记录消费位置;
  • 机器学习模型之类的特定应用状态;

注意:流计算长时间运行,使用时一定要考虑state的清理。

在Flink里状态可以分为两类:operator state(算子状态)和keyed state(键值分区状态),下面我们详细的介绍着两种state。

第2章 Flink中的State

2.1 Operator state(算子状态)

Operator state的作用域是算子任务,所有在同一个并行任务之内的记录都能访问到相同的state。注意Operator state不能通过其他任务访问,无论任务是否来自相同算子。

flink 获取算子 id flink 算子状态_流计算_02

Flink为operator state提供三种语义:

  • list state:列表状态,state表示为一个列表
  • union list state:联合列表状态,state表示为一个列表,但此状态恢复的方式与list state有所不同
  • broadcast state:广播状态,顾名思义,将state广播给每个算子任务,专门为需要保证算子的每个任务状态都相同的业务场景而设计。

2.2 Keyed state(键值分区状态)

Keyed state是按照算子输入数据所定义的键值来进行维护或访问。Flink为每个key都维护了一个状态实例,该实例总是位于处理对应key值记录的算子任务上。在算子处理数据时,Flink会自动把Keyed state访问范围限制为当前记录的Key值。也就是说,所有key值相同的记录都能访问到一样的state。

flink 获取算子 id flink 算子状态_flink_03

第3章 State backend(状态后端)

在Flink中,每个并行任务都会把state维护在本地,而state的存储、访问、维护,就是由state backend来完成。state backend主要负责:本地状态的管理、将本地state以checkpoint的方式写入远端存储。

下面我们介绍一下目前Flink当中三种state backend。

3.1 Memory

MemoryStateBackend的特点:

  • 基于JVM Heap内存,注意OOM风险
  • 持久化时State传输到远端Jobmanager,并存储在JobManager当中,而JobManager同样时存储在内存当中。
  • Memory内,在传输到远端DFS的时候需要经过一个序列化和反序列化的过程。

存储方式:

  • 本地存储:TaskManager的内存中;
  • 远端存储:JobManager的内存中。

适用场景:

  • 开发测试使用,或者状态小的流计算场景。

3.2 FS

FsStateBackend的特点:

  • 基于JVM Heap内存,注意OOM风险;
  • 持久化时State存储到文件系统当中,文件目录和文件名上传到远端的JobManager,State不上传到JobManager;
  • 本地文件的状态后端,支持全量CP,不支持增量CP。

存储方式:

  • 本地存储:TM的内存中;
  • 远端存储:本地文件系统或分布式文件系统(如:HDFS)。

适用场景:

  • 适合状态较大的高可用场景。

3.3 RocksDB

RocksDBStateBackend的特点:

  • 基于RocksDB,操作本地文件系统。
  • State可以维护Disk里,每次读取的时候需要经过序列化和反序列化的一个过程,传输到远端DFS的时候就不要在进行序列化和反序列化的操作。
  • 状态不上传到JobManager,支持增量持久化,增量CP。
  • 如果要在Flink里使用RocksDB作为State backend,需要将相关jar包引入,RocksDB在Flink中使用属于插件类型应用。

存储方式:

  • 本地存储:RocksDB;
  • 远端存储:分布式文件系统(如HDFS)。

使用场景:

  • 适合大状态高可用场景,有增量CP的性能优势。