目录
目录
(2) 使用Manage State,Flink自动实现state保存和恢复
(3) 自定义state 自行实现实现checkpoint接口
背景
Flink相对于Storm和Spark Stream比较大的一个优势就是State,pipline中可以保存状态,这对于解决业务是有巨大的帮助,否则将需要借助三方工具来时间状态的存储和访问。
正文
State
什么是State(状态)?
- 某task/operator在某时刻的一个中间结果
- 快照(shapshot)
- 在flink中状态可以理解为一种数据结构
- 举例
对输入源为<key,value>的数据,计算其中某key的最大值,如果使用HashMap,也可以进行计算,但是每次都需要重新遍历,使用状态的话,可以获取最近的一次计算结果,减少了系统的计算次数 - 程序一旦crash,恢复
- 程序扩容
State类型
总的来说,state分为两种,operator state和key state,key state专门对keystream使用,所包含的Sate种类也更多,可理解为dataStream.keyBy()之后的Operator State,Operator State是对每一个Operator的状态进行记录,而key State则是在dataSteam进行keyBy()后,记录相同keyId的keyStream上的状态key State提供的数据类型:ValueState<T>、ListState<T>、ReducingState<T>、MapState<T>。
operator state种类只有一种就是ListState<T> ,flink官方文档用kafka的消费者举例,认为kafka消费者的partitionId和offset类似flink的operator state
State理解
state分为operator state和key state两种,都属于manage state,优势是可以结合checkpoint,实现自动存储状态和异常恢复功能,但是state不一定要使用manage state,在source、windows和sink中自己声明一个int都可以作为状态进行使用,只不过需要自己实现快照状态保存和恢复。
State实战
import org.apache.flink.api.common.functions.RichFlatMapFunction;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
/**
* Created by authoe on 2018/9/12.
*/
public class StateTest {
public static void main(String[] args) throws Exception{
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(4).fromElements(Tuple2.of(1L,1L),Tuple2.of(2L,2L),Tuple2.of(3L,2L),Tuple2.of(4L,3L))
.keyBy(0).flatMap(new RichFlatMapFunction<Tuple2<Long,Long>, Object>() {
private transient ValueState<Tuple2<Long,Long>> sum;
@Override
public void flatMap(Tuple2<Long, Long> longLongTuple2, Collector<Object> collector) throws Exception {
Tuple2<Long,Long> curSum = sum.value();
curSum.f0+=1;
curSum.f1+=longLongTuple2.f1;
System.out.println("+");
sum.update(curSum);
if(curSum.f0>0){
System.out.println("-");
collector.collect(Tuple2.of(curSum.f0,curSum.f1));
sum.clear();
}
}
@Override
public void open(Configuration parameters) throws Exception {
ValueStateDescriptor<Tuple2<Long,Long>> descriptor = new ValueStateDescriptor<Tuple2<Long, Long>>("avg", TypeInformation.of(
new TypeHint<Tuple2<Long, Long>>() {}),Tuple2.of(0L,0L));
sum = getRuntimeContext().getState(descriptor);
}
}).print();
env.execute();
}
}
CheckPointing
(1)介绍,实现方式分类
checkpoint可以保存窗口和算子的执行状态,在出现异常之后重启计算任务,并保证已经执行和不会再重复执行,检查点可以分为两种,托管的和自定义的,托管检查点会自动的进行存储到指定位置:内存、磁盘和分布式存储中,自定义就需要自行实现保存相关,实现checkpoint有如下两种方式:
- 使用托管State变量
- 使用自定义State变量实现CheckpointedFunction接口或者ListCheckpoint<T extends Serializable>接口
下面将会给出两种方式的使用代码
(2) 使用Manage State,Flink自动实现state保存和恢复
下面先给出托管状态变量(manage stata)使用代码,后面给出了代码执行的打印日志。
代码分析:
- 代码每隔2s发送10条记录,所有数据key=1,会发送到统一窗口进行计数,发送超过100条是,抛出异常,模拟异常
- 窗口中统计收到的消息记录数,当异常发生时,查看windows是否会从state中获取历史数据,即checkpoint是否生效
- 注释已经添加进代码中,有个问题有时,state.value()在open()方法中调用的时候,会抛出null异常,而在apply中 使用就不会抛出异常。
Console日志输出分析:
- 四个open调用,因为我本地代码默认并行度为4,所以会有4个windows函数被实例化出来,调用各自open函数
- source发送记录到达100抛出异常
- source抛出异常之后,count发送统计数丢失,重新从0开始
- windows函数,重启后调用ope