1. 什么是flink state

由一个任务维护,并且用来计算某个结果的数据,都属于这个任务的状态,可以认为状态就是一个本地变量,可以被任务的业务逻辑访问。
Flink 会进行状态管理,包括状态一致性、故障处理以及高效存储和访问,以 便开发人员可以专注于应用程序的逻辑。
Flink有两种基本类型的状态:托管状态(Managed State)和原生状态(Raw State)。
两者的区别:Managed State是由Flink管理的,Flink帮忙存储、恢复和优化,Raw State是开发者自己管理的,需要自己序列化。
具体区别有:
1. 从状态管理的方式上来说,Managed State由Flink Runtime托管,状态是自动存储、自动恢复的,Flink在存储管理和持久化上做了一些优化。当横向伸缩,或者说修改Flink应用的并行度时,状态也能自动重新分布到多个并行实例上。Raw State是用户自定义的状态。
从状态的数据结构上来说,Managed State支持了一系列常见的数据结构,如ValueState、ListState、MapState等。Raw State只支持字节,任何上层数据结构需要序列化为字节数组。使用时,需要用户自己序列化,以非常底层的字节数组形式存储,Flink并不知道存储的是什么样的数据结构。
2. 从具体使用场景来说,绝大多数的算子都可以通过继承Rich函数类或其他提供好的接口类,在里面使用Managed State。Raw State是在已有算子和Managed State不够用时,用户自定义算子时使用。
对Managed State继续细分,它又有两种类型:Keyed State和Operator State。
为了自定义Flink的算子,可以重写Rich Function接口类,比如RichFlatMapFunction。使用Keyed State时,通过重写Rich Function接口类,在里面创建和访问状态。对于Operator State,还需进一步实现CheckpointedFunction接口。
2. 算子状态(operator state)
算子状态的作用范围限定为当前算子任务,当前算子任务中的所有数据都可以访问到相同的状态,但不能被另一个算子任务访问,哪怕是处理同一类算子的并行任务。
2.1 算子状态的数据结构
1. 列表状态
即采用List的数据结构,存储多个数据作为状态数据
2. 联合列表状态
也是采用List的数据结构,但和列表状态的区别在于其在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复。
列表状态在恢复程序的时候,会依据恢复后的并行度,将列表中的状态数据进行拆分,拆分为新的列表状态后在分发给各个并行算子。
而联合列表状态则是将所有的列表状态合并为一个完整的列表状态,然后给每一个新的并行算子任务发送一份作为自身状态。
3. 广播状态:这种情况比较特殊,其适用于各个算子之间要求状态值相同的情况,比如说一些配置参数,各个算子公用一套配置参数,这种情况就比较适合广播状态。
2.2 算子状态api使用
算子状态的api应用较少,比较常见的 operator state 是 source state,例如记录当前 source 的 offset,这个在以kafka作为source的时候非常常用,我们可以通过记录offset来判断kafka中的消息积压情况。
主要是在算子实现类中实现ListCheckpointed接口,就可以实现算子状态的存储和恢复。
还有一种实现CheckpointedFunction接口的,但比较复杂,实现ListCheckpointed比较简单清晰,但通过CheckpointedFunction接口实现会比较灵活。
public class OperatorStateTest1 {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//从文本文件中按行读取数据
DataStreamSource<String> streamSource = env.readTextFile("word.txt");
SingleOutputStreamOperator<Tuple2<String, Integer>> sum = streamSource.flatMap(new WordCount.MyFlatMapper())
.keyBy(0)
.sum(1);
sum.print();
env.execute();
}
//通过算子状态来记录统计一下处理的数据数量
public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>>, ListCheckpointed<Integer> {
//其实算子状态很简单,直接定义一个变量就能实现所需要的数据量统计
int count = 0;
//仅通过count这个状态变量我们依据实现了所需要的的统计功能,但是问题在于,当程序异常终止又重新启动后,
//flink要如何恢复这个变量值?
//我们肯定不能重新读取数据,把所有数据重新处理一遍
//所以我们可以通过Flink提供的接口来实现状态数据的快照保存和恢复
//MyFlatMapper实现ListCheckpointed接口即可
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
//统计一下处理一条数据
count++;
//按空格分词
String[] s1 = s.split(" "

最低0.47元/天 解锁文章
1169

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



