本文主要讲解Flink State(状态)的核心概念与实践。Flink根据是否需要保存中间结果,将计算分为有状态计算和无状态计算两种类型。

状态类型

  • 有状态计算(Stateful Computation):需要保存中间结果或状态,依赖之前或之后的事件进行数据处理。典型应用场景包括窗口聚合、模式检测、数据去重等。状态后端支持MemoryStateBackend、FsStateBackend、RocksDBStateBackend。
  • 无状态计算(Stateless Computation):每个数据记录的处理都是独立的,不需要保存中间状态。典型算子包括Map、Filter、FlatMap。

Flink State分类

  • ValueState:单值状态,可通过update方法更新状态值,通过value()方法获取状态值
  • ListState:状态值为列表,可通过add方法往列表中附加值
  • ReducingState:通过ReduceFunction合并到单一状态值
  • MapState:状态值为Map,用户通过put和putAll方法添加元素

Keyed State vs Operator State

  • Keyed State:与特定Key相关联的状态,只能应用于KeyedStream类型的数据集。核心特性包括Key关联性、自动分区、高效访问。通过KeyGroups机制进行管理,支持动态扩缩容和故障恢复。
  • Operator State:与算子实例绑定,不依赖于数据中的key。支持动态扩容/缩容,提供三种重新分配策略:均匀分配、全量广播、自定义分配。

状态管理形式

  • 托管状态(Managed State):由Flink运行时环境统一管理,自动转换为高效内存数据结构,通过Checkpoint机制提供exactly-once状态保证
  • 原生状态(Raw State):算子需要自行维护状态数据结构,需要自己实现状态序列化逻辑

状态后端比较

  • MemoryStateBackend:存储在JVM堆内存,速度最快,适合测试/小状态
  • FsStateBackend:存储在文件系统,适合常规生产环境,单任务可达TB级
  • RocksDBStateBackend:存储在RocksDB,适合超大状态场景,仅受磁盘容量限制