本文主要讲解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,适合超大状态场景,仅受磁盘容量限制