状态管理的基本概念
flink状态是什么
flink的状态,简单来说,就是有状态函数或者算子在处理数据时,保存在本地的一个变量,这个变量可以是自定义结构的数据,用于记录计算时产生的结果,或者其他的数据。有状态的操作在对每条数据进行处理时,会基于状态计算或更新状态信息,如下图:
为什么要管理状态?
使用了状态,为什么要管理状态?因为实时作业需要7*24不间断的运行,需要应对不可靠的因素而带来的影响。
flink状态的分类
managed State & Raw State
managed State 是Flink自动管理的State,而Raw State是原生态
State,两者的区别如下:
•从状态管理方式的方式来说,Managed State 由Flink Runtime管理,
自动存储,自动恢复,在内存管理上有优化;而Raw State需要用户
自己管理,需要自己序列化,Flink不知道 State 中存入的数据是什
么结构,只有用户自己知道,需要最终序列化为可存储的数据结构。
•从状态数据结构来说,Managed State 支持已知的数据结构,如Value、
List、Map 等。而Raw State 只支持字节数组 ,所有状态都要转换为
二进制字节数组才可以。
•从推荐使用场景来说,Managed State 大多数情况下均可使用,而Raw
State 是当Managed State不够用时,比如需要自定义Operator 时,
推荐使用Raw State。
managed State分为两种,一种是keyedState;另外一种是operatorState。
flink容错机制
flink的容错机制都是基于checkpoint(状态一致性检查)的,简单来说,就是flink在计算过程中,将状态保存至checkpoint,当遇到故障终止任务后,可以从checkpoint中恢复数据并继续任务,达到容错的目的。
什么是checkpoint
Checkpoint是flink故障恢复机制的核心,可以保证数据精准一次消费。所谓checkpoint,其实就是有状态流在某一时间点的状态的快照。这个时间点应该是所有任务都恰好处理完同一个输入数据的时候,即在整个flink程序中,最后一个操作也已经处理完这条数据的时候。未被处理完的其他数据的状态不会被保存。
当遇到故障,导致应用停止后。第一步将会重启应用,然后会从checkpoint中恢复状态,此时状态将会恢复到上一个checkpoint时的状态,然后继续正常运行应用。
flink的checkpoint与spark-streaming的checkpoint不同,spark-streaming是批处理,所以它的checkpoint比较简单,因为底层是rdd,所以只要把rdd保存起来就可以了,但是这就有一个缺点,那就是一旦发生故障,可能有一整个批次的数据都要重新计算,加入数据量很大的花,将会消耗更多的事件;而flink是流式处理,它的checkpoint针对的是每一条数据(可以设置每处理一条都保存一次,也可以设置一段事件保存一次),所以它的checkpoint更加复杂,但是发生故障后对整个应用的影响也更小。
chekpoint中有类似watermark的机制,称为checkpoint-barrier,用于检查点对齐,当收到checkpoint-barrier时保存快照。checkpoint-barrier有三个属性:ID,timestamp,checkpoint-options。每个有状态操作遇到checkpoint-barrier都会保存快照,而只有当最后一个操作保存了快照之后,这次checkpoint才算完成。
如何使用checkpoint
StreamExecutionEnvironment中有一个CheckpointConfig对象,当调用环境对象的env.enableCheckpointing(1000)方法时,实际上是调用CheckpointConfig对象的各种set方法。如:
通过env对象开启checkpoint,实际上是调用checkpointconfig的setCheckpointInterval方法:
//env的enableCheckpointing方法
public StreamExecutionEnvironment enableCheckpointing(long interval) {
checkpointCfg.setCheckpointInterval(interval);
return this;
}
checkpointconfig中的setCheckpointInterval方法
//checkpointconfig
public void setCheckpointInterval(long checkpointInterval) {
if (checkpointInterval <= 0) {
throw new IllegalArgumentException("Checkpoint interval must be larger than zero");
}
this.checkpointInterval = checkpointInterval;
}
启用checkpoint
默认情况下,checkpoint是关闭的,需要调用环境对象StreamExecutionEnvironment的enableCheckpointing(n)
方法以启用checkpoint,参数n代表每隔n毫秒发出一个checkpointbarrier。
以下是一个设置checkpoint的样例:
StreamExecutionEnvironment env=StreamExecutionEnvironment.getExecutionEnvironment();
//生成checkpoint间隔,单位毫秒
env.enableCheckpointing(1000);
//消息一次性语义
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
//相邻的checkpoint最小时间间隔,防止checkpoint频繁制作,
//比如:一次checkpoint花费800毫秒,再过200毫秒开始下一次制作checkpoint
//当设置MinPauseBetweenCheckpoints后会等500毫秒后才开始制作checkpoint
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);
//制作超时时间
env.getCheckpointConfig().setCheckpointTimeout(60000);
//同时有1个线程在做checkpoint
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
//当作业被cancel的时候做相应操作,目前配置的时作业cancel时state会被清除
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
checkPoint做的越频繁,恢复时追数据就会相对减少,同时checkpoint相应的也会有一些IO消耗。setCheckpointTimeout表示做checkpoint多久超时,如果checkpoint在1min之内尚未完成,说明checkpoint超时失败。
如果觉得文章能帮到您,欢迎关注微信公众号:“蓝天Java大数据” ,共同进步!