Flink笔记整理(六)
完整系列在公众号:是十三不是四十三,欢迎关注~
文章目录
- Flink笔记整理(六)
- 八、状态管理
- 8.1 Flink中的状态
- 概述
- 状态的分类
- 8.2 按键分区状态(Keyed State)
- 值状态(ValueState)
- 列表状态(ListState)
- Map状态(MapState)
- 归约状态(ReducingState)
- 聚合状态(AggregatingState)
- 状态生存时间(TTL)
- 8.3 算子状态(Operator State)
- 列表状态(ListState)
- 联合列表状态(UnionListState)
- 广播状态(BroadcastState)
- 8.4 状态后端(State Backends)
- 状态后端的分类(HashMapStateBackend/RocksDB)
- 如何选择正确的状态后端
- 状态后端的配置
- 总结
八、状态管理
8.1 Flink中的状态
概述
状态的分类
- 托管状态(Managed State)和原始状态(Raw State)
Flink的状态有两种:托管状态(Managed State)和原始状态(Raw State)。托管状态就是由Flink统一管理的,状态的存储访问、故障恢复和重组等一系列问题都由Flink实现,我们只要调接口就可以;而原始状态则是自定义的,相当于就是开辟了一块内存,需要我们自己管理,实现状态的序列化和故障恢复。
通常我们采用Flink托管状态来实现需求。
- 算子状态(Operator State)和按键分区状态(Keyed State)
接下来重点就是托管状态(Managed State)。
在Flink中,一个算子任务会按照并行度分为多个并行子任务执行,而不同的子任务会占据不同的任务槽(task slot)。由于不同的slot在计算资源上是物理隔离的,所以Flink能管理的状态在并行任务间是无法共享的,每个状态只能针对当前子任务的实例有效。
而很多有状态的操作(比如聚合、窗口)都是要先做keyBy进行按键分区的。按键分区之后,任务所进行的所有计算都应该只针对当前key有效,所以状态也应该按照key彼此隔离。在这种情况下,状态的访问方式又会有所不同。
基于这样的想法,又可以将托管状态分为两类:算子状态和按键分区状态。
聚合算子必须在keyBy之后才能用
另外,也可以通过富函数类(Rich Function)来自定义Keyed State,所以只要提供了富函数类接口的算子,也都可以使用Keyed State。所以即使是map、filter这样无状态的基本转换算子,我们也可以通过富函数类给它们“追加”Keyed State。比如RichMapFunction、RichFilterFunction。在富函数中,我们可以调用.getRuntimeContext()获取当前的运行时上下文(RuntimeContext),进而获取到访问状态的句柄;这种富函数中自定义的状态也是Keyed State。从这个角度讲,Flink中所有的算子都可以是有状态的。
无论是Keyed State还是Operator State,它们都是在本地实例上维护的,也就是说每个并行子任务维护着对应的状态,算子的子任务之间状态不共享。
8.2 按键分区状态(Keyed State)
按键分区状态(Keyed State)顾名思义,是任务按照键(key)来访问和维护的状态。它的特点非常鲜明,就是以key为作用范围进行隔离。
需要注意,使用Keyed State必须基于KeyedStream。没有进行keyBy分区的DataStream,即使转换算子实现了对应的富函数类,也不能通过运行时上下文访问Keyed State。
Flink按键分区状态(Keyed State)以及代码
值状态(ValueState)
ValueState
列表状态(ListState)
ListState
Map状态(MapState)
ValueState
归约状态(ReducingState)
ReducingState
聚合状态(AggregatingState)
AggregatingState
状态生存时间(TTL)
TTL
8.3 算子状态(Operator State)
算子状态(Operator State)就是一个算子并行实例上定义的状态,作用范围被限定为当前算子任务。算子状态跟数据的key无关,所以不同key的数据只要被分发到同一个并行子任务,就会访问到同一个Operator State。
算子状态的实际应用场景不如Keyed State多,一般用在Source或Sink等与外部系统连接的算子上,或者完全没有key定义的场景。比如Flink的Kafka连接器中,就用到了算子状态。
当算子的并行度发生变化时,算子状态也支持在并行的算子任务实例之间做重组分配。根据状态的类型不同,重组分配的方案也会不同。
算子状态也支持不同的结构类型,主要有三种:ListState、UnionListState和BroadcastState。
列表状态(ListState)
ListState
联合列表状态(UnionListState)
UnionListState
广播状态(BroadcastState)
BroadcastState
8.4 状态后端(State Backends)
在Flink中,状态的存储、访问以及维护,都是由一个可插拔的组件决定的,这个组件就叫作状态后端(state backend)。状态后端主要负责管理本地状态的存储方式和位置。
状态后端的分类(HashMapStateBackend/RocksDB)
状态后端的分类
如何选择正确的状态后端
如何选择正确的状态后端
状态后端的配置
状态后端的配置