在flink中,state是其重要的特性之一。有了state使得在数据流上进行状态的计算成为了可能,为flink的发展做出了重要贡献。没有state时需要在flink上进行状态的计算将会非常复杂且在复杂场景下无法实现,如集群宕机时状态快照的保存。无论是使用flink和MySQL还是flink和其他的存储引擎都存在一些缺陷。既然state这么重要,不妨我们一起来学习、理解和使用state。

一、什么是state

        在flink官方的定义中,将其定义为是一个能够在数据流上进行状态计算的框架。结合实际使用,state泛指在flink中有状态函数或运算符在对各个数据流的处理过程中存储的数据。注意:状态数据可以修改、查询,根据自己的业务场景,保存历史数据或者中间结果到状态(state)中。

        state分为Keyed state和Operate state。Keyed state通常和key相关,仅可使用在KeyedStream的方法和算子中。Keyed state的初始化是在open函数中,读写操作一般定义在用户实现的算子函数中,例如RichMapFunction的map中。在checkpoint时,由flink自行备份当前state到checkpoint快照中,无需用户手动管理快照触发和生成的细节。而Operate state(non-keyed state),每个Operate state和一个并发实例进行绑定。Operate state需要用户实现CheckpointedFunction或ListCheckpointed,通过手动覆写接口中的函数来定义state的初始化和快照生成逻辑。

二、如何理解state

        flink中的state分为有状态计算和无状态计算。在实际开发中,如何理解这两种计算的差异呢?下面我们通过其定义和举例的方式分别对其进行说明。

  • flink中的有状态计算和无状态计算:
  • 有状态计算:指新进入flink的数据流需要和历史的数据流进行相关的操作后,才能计算出正确的结果。
  • 无状态计算:数据进入flink后,只需要对当前的数据流进行处理就能得到想要的正确的结果。
  • 举例说明:
  • 有状态计算,统计某一个单词出现的次数,随着输入流的不断输入,当某一个单词出现后,计数器加1,再次出现时,计数器加1后变为2,这类操作属于有状态计算操作,对新输入的数据流的操作总是会用到历史的数据流。
  • 无状态计算,当输入流中yn的值是1时,对应输出“是”,yn的值是0或其他值时,对应输出“否”。这种对输入的数据流进行处理了就能得到相要的正确结果。一般情况下,无状态计算是一个幂等操作。

三、state中常用参数配置

配置项

配置值

释义说明

akka.ask.timeout

60s

设置超时时间

state_backend_rocksdb_ttl_

compaction_filter_enabled

true

后台开启多线程压缩时清除

state_backend

rocksdb

状态存储介质,flink提供了内存、文件系统和rocksdb三种存储介质。

state_backend_incremental

true

增量设置checkpoint

classloader_resolve_order

child-first

class解析顺序。默认情况下,flink会优先在child classloader(用户代码的classloader)中查找user-code classes,然后再在parent classloader(系统的classloader)中查找user-code classes。此机制可避免job与flink系统的版本冲突。

apus_slotmanager_slot_

placement_policy

SLOT

槽,flink中计算资源的基本单位,TM的一个slot代表一个可用线程,该线程具有固定的内存,但CPU是共享的。一个槽在同一时间执行一个任务,TM拥有一个或多个槽。

apus.checkpoint.delete.

recursive

false

递归删除checkpoint

taskmanager.memory.

network.fraction

0.25

网络缓存占flink总内存的比例

taskmanager.memory.

network.min

268435456

网络缓存的最小值

taskmanager.memory.

network.max

2147483648

网络缓存的最大值

taskmanager.network.

request-backoff.max

120000

下游输入请求上游输出的超时回退时间(单位:毫秒)

state.backend.rocksdb.localdir

/export/io_tmp_dirs/rocksdb

保存状态的rocksdb的文件路径

apus_cp_path_prefix

hdfs://[ns]/user/[user]/flink/cp

设置CP(checkpoint)路径

apus_sp_path_prefix

hdfs://[ns]/user/[user]/flink/sp

设置SP(savepoint)路径

         以上表格中例举的参数仅为其中的一部分,在实际生产中,可根据集群的实际情况进行参数的增减,确保集群状态最优。

四、state应用场景

1、缓存场景

        上文提到的计数器,每次都是基于已有的数在其上加1,这里对计数器里数据的存储即是其应用场景之一。再比如,多表关联时,由于每一表的数据流到达算子的时间有前后,可以把先到的数据流存储到state中,待其他的数据流到达后再把state的数据取出一起计算。

2、快照

        流式任务上下线或宕机时,把停机时的数据流信息存储到state,便于集群恢复时从state获取停机时的数据流信息,便于精确恢复数据。