1、检查点基础
一致性检查点:当所有任务都处理完同一个相同的输入数据时,给所有任务拍一个快照,这个快照就是一致性检查点。它默认不开启。
所有任务都处理完同一个相同的输入数据时,状态由状态后端保存,这些状态对应的元数据由jobmanager保
存。
source算子一定要保存状态,因为有些数据处理失败后未成功保存checkpoint,而这些数据已经被source读取了,source不保存状态这部分数据就丢失了。
从一致性检查点恢复的过程:
1、重启应用(flink1.9之后可以局部重启)。
2、从checkpoint中读取状态,将状态重置。
3、Source重置偏移量。
2、检查点算法:
基于chandy-lamport算法的分布式快照,将检查点保存和数据处理分开,不会暂停整个应用。
Flink检查点算法用到了一种被称为检查点分界线checkpoint-barrier的特殊数据形式,用来将一条流上的
数据按照不同的检查点分开。
barrier之前的数据导致的状态改变都会包含在该barrier对应的checkpoint中,barrier之后的数据都会包
含在之后的barrier对应的checkpoint中。
具体实现:
1、Jobmanager会向每个source任务发送一条带有新检查点id的消息。
2、source收到消息后将自身状态保存到checkpoint,然后向JM报告,并以广播的形式向下游发送
barrier。
3、当transformations收到上游所有source发送的相同的barrier之后,将状态写入检查点并向下
游广播barrier。对于barrier已到达的source,后续数据会被缓存,对于barrier未到达的
source,后续数据会被正常处理。
4、当sink收到上有所有transformations发送的相同的barrier之后,将状态写入检查点并向JM报
告检查点完成。
3、检查点配置
env.enableCheckpointing(1000[,EXACTLY_ONCE]);
设定checkpoint间隔和模式,模式还可以是AT_LEAST_ONCE
env.getCheckpointConfig().setCheckpointTimeout(100000);
设置checkpoint超时时间
env.getCheckpointConfig().setMaxCocurrentCheckpoints(2);
最多同时处理2个checkpoint。
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);
前一个checkpoint结束到后一个checkpoint开启的最小间隔。与上一个矛盾。
env.getCheckpointConfig().setTolerableCheckpointFailureNumber(10);
允许失败的检查点个数,默认是0,即不允许失败。
env.getCheckpointConfig().setPreferCheckpointForRecovery(false);
从checkpoint恢复是否考虑savepoint,false考虑。默认为false
env.getCheckpointConfig().enableExternalizedCheckpoints
(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
当作业被取消时,checkpoint是不会被清理。DELETE_ON_CANCELLATION为清理,也是默认的。
env.setStateBackend(new FsStateBackend() );
存储策略
4、恢复&savepoint
job失败取消job,重新提交任务时指定checkpoint路径。
但是checkpoint文件很多,可能找不到对应的那一个,怎么办呢?
可以使用savepoint,savepoint相当于手动执行checkpoint,可以指定checkpoint路径。
常用于故障恢复、手动备份、应用暂停和重启以及版本迁移等。
flink savepoint ${任务id} ${checkpoint保存路径}
重启策略配置
默认重启策略:默认生效,会无限重启且自动恢复,但可能会隐藏真正的bug。
关闭重启策略:env.setRestartStrategy(RestartStrategies.noRestart());
外包重启策略:env.setRestartStrategy(RestartStrategies.fallbackRestart());
让资源管理器或调度平台去管理重启。
固定延迟重启策略 env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,60000));
每60秒重启一次,最多重启3次 (用的多)
失败率重启策略:env.setRestartStrategy(RestartStrategies.
failureRateRestart(3,Time.minutes(5), Time.seconds(60) ));
5分钟内失败小于3次,每 60秒重启1次 (用的多)
5、状态一致性
分类:
at-most-once\at-least-once\exactly-once
flink实现exactly-once的原因:
checkpoint保存的是所有任务处理完同一个输入数据的状态,且source支持重置偏移量,且sink采
取两阶段提交的方式。
而端到端的的exactly-once不仅flink内部要保证exactly-once,且source和sink也要保证exactly。
source端精准一次:要可以重新设置读取数据的位置。
sink端精准一次:
实现的两种方式:
幂等写入:
幂等写入就是对一个操作无论重复执行多少次,都不改变最初的结果。写入ES/Redis。(用得少)
事务写入:
预写日志:
结果数据保存为state,当checkpoint成功后,一次性sink结果数据。变成了批处
理,延迟加大。(用得少)
DataStream api中提供了一个类:GenericWriteAheadSink。
两段提交:
sink任务和checkpoint保存在一个事务内,sink任务先预提交到外部系统,当
checkpoint完成时,事务才提交。保存到kafka就是这种方式。(用得多)
对外部系统的要求:
1、必须支持事务,且事务提交要是幂等性操作。
2、sink任务、checkpoint、外部系统三者超时时间必须一致。
DataStream api提供了一个类:TwoPhaseCommitSinkFunction。
构建的事务对应着checkpoint,等chaeckpoint真正完成的时候,才会将数据sink入外部系统。