Flink系统知识之:容错与State状态管理
状态在Flink中叫作State,用来保存中间计算结果或者缓存数据。根据是否需要保存中间结果,分为无状态计算和有状态计算。对于流计算而言,事件持续不断地产生,如果每次计算都是相互独立的,不依赖于上下游的事件,则是无状态计算。如果计算需要依赖于之前或者后续的事件,则是有状态计算。State是实现有状态计算下的Exactly-Once的基础。
Flink的State提供了对State的操作接口,向上对接Flink的DataStream API,让用户在开发Flink应用的时候,可以将临时数据保存到State中,从State中读取数据。在运行的时候,在运行层面上与算子、Function体系融合,自动对State进行备份(checkpoint),一旦出现异常能够从保存的State中恢复状态,实现Exactly-Once。
状态类型
按照数据结构的不同,Flink中定义了多种State,应用于不同的场景,具体如下。
(1)ValueState
即类型为T的单值状态。这个状态与对应的Key绑定,是最简单的状态。可以通过update方法更新状态值,通过value()方法获取动态值。
(2)ListState
即Key上的状态值为一个列表。可以通过add方法往列表中添加值,也可以通过get()方法返回一个Iterable来遍历状态值。
(3)ReducingState
这种状态通过用户传入的reduceFunction,每次调用add方法添加值时,会调用reduceFunction,最后合并到一个单一的状态值。
(4)AggregatingState<IN, OUT>
聚合State,和(3)不同的是,这里聚合的类型可以是不同的元素类型,使用add(IN)来加入元素,并使用AggregateFunction函数计算聚合结果。
(5)MapState<UK, UV>
使用Map存储Key-Value对,通过put(UK, UV)或者putAll(Map<UK, UV>)来添加,使用get(UK)来获取。
(6)FoldingState<T, ACC>
跟ReducingState有点类似,不过它的状态值类型可以与add方法中传入的元素类型不同。已被标记为废弃,不建议使用。
KeyedState和OperatorState
State按照是否有Key划分为KeyedState和OperatorState两种。
| 按是否有Key划分 | 支持的State |
|---|---|
| KeyedState | ValueState ListState ReducingState AggregatingState MapState FoldingState |
| OperatorState | ListState |
KeyedState
在KeyedStream中使用。状态是跟特定的Key绑定的,即KeyedStream流上的每一个Key对应一个State对象。在这种情况下,可以通过getRuntimeContext.getState方法来获取每个key绑定的对应的State对象。比如,假设正在处理一个流并且对 key 进行分组,并且有一个 ValueState 来存储每个 key 的最后修改时间,那么每个唯一的 key 都会有一个独立的 ValueState 实例。
关于 Keyed State 的几点关键信息:
- Keyed State 只能用于 KeyedStream,无法在非键控的流或操作符中使用。
- 同一时间,一个 Keyed State 只能访问当前处理的事件的 key 的状态。
算子状态OperatorState
与KeyedState不同,OperatorState跟一个特定算子的一个实例绑定,整个算子只对应一个State实例。Operator State 可以用于保存操作符级别的信息,此信息跨所有输入数据存在。它与特定的键无关。在有状态操作符中使用 Operator State 可以用于存储和检索状态信息。例如,保存 Kafka source 的 offset 就是使用 Operator State。
Flink 使用 Operator State 进行全局操作,如读/写外部系统的偏移量,保存所有 key 的全局聚合等。比如,源(Source)操作符在 Flink 中经常使用 Operator State,以保存并恢复读取的位置。
一个重要的特性是,Flink 可以将 Operator State 分布在操作符的所有并行实例中。这意味着,当你的作业需要重新平衡(例如,操作符的并行度改变)时,Flink 可以通过特定的分布和复制策略(只复制,广播等)重新分配 Operator State。
OperatorState目前只支持使用ListState。
下述提供了一个案例方法,在算子中自定义OperatorState状态并实现自定义的快照逻辑和状态初始化逻辑:
public class MySinkFunction implements SinkFunction<Long>, CheckpointedFunction {
private ListState<Long> listState;
@Override
public void invoke(Long value, Context context) throws Exception {
// 用户自定义业务逻辑
listState.add(value);
}


520

被折叠的 条评论
为什么被折叠?



