【白话Flink基础理论】Flink中的容错机制——检查点CheckPoint&屏障Barrier&保存点SavePoint

——wirte by 橙心橙意橙续缘,

前言

白话系列
————————————————————————————
也就是我在写作时完全不考虑写作方面的约束,完全把自己学到的东西、以及理由和所思考的东西等等都用大白话诉说出来,这样能够让信息最大化的从自己脑子里输出并且输入到有需要的同学的脑中。PS:较为专业的地方还是会用专业口语诉说,大家放心!

白话Flink系列
————————————————————————————
主要是记录本人(国内某985研究生)在Flink基础理论阶段学习的一些所学,更重要的是一些所思所想,所参考的视频资料或者博客以及文献资料均在文末放出.由于研究生期间的课题组和研究方向与Flink接轨较多,而且Flink的学习对于想进入大厂的同学们来说也是非常的赞,所以该系列文章会随着本人学习的深入来不断修改和完善,希望大家也可以多批评指正或者提出宝贵建议。

一致性检查点CheckPoints

Flink故障恢复的核心,就是应用状态的一致性检查点CheckPoints。

检查点的概念

在这里插入图片描述
checkpoints到底是什么呢?
——————————————————————————————————————————
其实就是所有任务的状态在某个时间点的一份快照。那数据不需要保存吗?数据丢失该怎么办呢?其实没关系的,像我们现在Flink的数据源一般是Kafka等消息队列,它们一般对于数据都会记录其偏移量offset,出错时只需要根据这个offset便可以恢复,所以Flink中的CheckPoints只需要保存状态即可。

时间点是什么时候呢?
——————————————————————————
就是所有任务都恰好处理完一个相同的输入数据的时候,也就是有数据到达Sink的时候就保存。为什么必须是这个时间点呢?因为这样的话我们能保证对于每个检查点来说,他所对应的offset(也就是当前处理到的数据)一定已经完成了全部的计算。这样恢复完我们就不对前面的状态做任何纠结,直接继续执行offset后续的数据即可;

明确了这些基本概念的含义以后,我们再来看一下上面这幅图吧。

对于图中的数据来说,我们知道当前已经处理到了第5个数据,而且由于sum_odd(求奇数的和1+3+5=9)是9,那么很明显当前这个5已经执行过该Task 了,所以可以进行检查点保存了,所以图中保存的检查点是5-6-9,采用的是内存状态后端,保存到了JobManager上。

从检查点中恢复状态

在这里插入图片描述

如果发生如图数据来说,checkpoint是怎么工作的呢?

  1. 首先,重启应用(Flink默认是重启全部应用,在Flink配置文件中还可以配置区域重启,也就是只重启故障的部分)。
    在这里插入图片描述
  2. 从CheckPoint中读取状态,将所有的状态重置。
    在这里插入图片描述
  3. 开始消费并处理检查点到发生故障之间的所有数据。
    在这里插入图片描述

可见,检查点的这种保存和恢复机制,为应用程序提供了“精确一次”(exactly-once)的一致性,因为所有算子都会被保存检查点并恢复所有状态,这样一来所有的输入流都会被重置到检查点完成时的位置。

检查点工作机制——屏障Barrier

为什么要有Barrier?
————————————————————————————————
准确一次(exactly once)的送达保证是实时计算的关键特性之一,这要求作业从失败恢复后的状态以及管道中的数据流要和失败时一致,通常这是通过定期对作业状态和数据流进行快照实现的。然而如果按照上面这样的方式主要有两点不足:

  • 首先,快照进行期间常常要暂停数据流的摄入,造成额外延迟和吞吐量下降;
  • 其次,快照会过度谨慎地将管道里正在计算的数据也随着状态保存下来,导致快照过于庞大。

针对以上两个问题,Apache Flink(下简称 Flink)引入了异步屏障快照(Asynchronous Barrier Snapshot, ABS)。第1点是由异步+屏障来解决的,Flink就不需要停止整个数据流上的Task来进行快照,而是只需要当前收到屏障的Task执行快照;第2点是由屏障来解决的,Flink通过屏障将本次快照的数据和下次快照的数据分隔开,这样只需要在收到屏障时进行快照,就可以保证在此之前的数据都到达了。

  • 基于Chandy-Lamport算法的分布式快照。
  • 将检查点的保存和数据处理分离开,不暂停整个应用。

也就是说不同的Task分别进行快照,然后由状态后端收到所有的将来自各个task的任务的快照拼在一起组成当前作业的Checkpoint。

Barrier的基本功能
————————————————————————————————————————
Flink 分布式快照里面的一个核心的元素就是流屏障(stream barrier)。
在这里插入图片描述

  • 屏障由 JobManager上的checkpoint协调器定时广播给计算任务所有的 Source,Source会直接保存Kafka的上一条数据的offset,其后伴随数据流一起流至下游。

  • 每个 barrier 是属于当前快照的数据与属于下个快照的数据的分割点。可以看到屏障将数据流分成了两部分数据(实际上是多个连续的部分),一部分是当前快照的数据,一部分下一个快照的数据。每个屏障会带有它的快照ID一直向下游流动。这个快照的数据都在这个屏障的前面。

  • 从图上看,数据是从左向右移动(右边的先进入系统),那么快照n包含的数据就是右侧到下一个屏障(n-1)截止的数据,图中两个灰色竖线之间的部分,也就是part of checkpoint n。

  • 另外屏障并不会打断数据的流动,因而屏障是非常轻量的。在同一个时刻,多个快照可以在同一个数据流中,这也就是说多个快照可以同时产生。

单流上Barrier的工作

在这里插入图片描述

如上图所示,每当接收到屏障,算子便会将对当前的状态做一次快照,成功后将屏障以广播形式传给下游。最后屏障会流至作业的 Sink,Sink 接受到屏障后即向 JobManager 确认,后者收到所有 Sink 的确认标志着一个完整快照的生成,也即生成了该快照id对应的checkpoint

所以,可以说Barrier的到来就是一个算子进行checkpoint的时间节点。当前Barrier之前的数据状态保存在当前的检查点中,之后的数据会保存在下一个检查点当中。

快照完成后,当前的快照窗口随之关闭,算子不会再向上游请求早于这个时间的数据,因为这些数据已经流过整个作业,被转化为作业状态的一部分,它已经是现在整个数据流上最新的快照了。

多流上Barrier的工作—对齐机制

多流与单流的整理情况是相似的,只是有一点不同。

其中有种比较特殊的情况是一个算子接收了两个数据流,比如对它们进行 windowed join 的情况,这时屏障会驱使算子对两个数据流进行校准(Aligning)——Barrier对齐。校准的每个步骤如下:

  • 从其中一个上游数据流接收到快照屏障 barrier n 后,算子会暂停对该数据流的处理,直到从另外一个数据流也接收到 barrier n 它才会重新开始处理对应该数据流。这种机制避免了两个数据流的效率不一致,导致算子的快照窗口包含不属于当前窗口的数据。
  • 算子暂停对一个数据流的处理并不会阻塞该数据流,而是将数据暂时缓存起来,因为这些数据属于快照 n+1 ,而不是当前的快照 n
    当另一个数据流的 barrier n 也抵达,算子会将所有正在处理的结果发至下游,随后做快照并发送 barrier n 到下游。
  • 最后,算子重新开始对所有数据流的处理,当然优先处理的是已经被缓存的数据

这种情况大家可以这么理解,不管是由于多个scource还是说split造成的多流,它里面含有的Barrier是一致的,因为Barrier的生成和向下传递机制都是广播,Barrier在生成的那一刻就相当于给它分配了要监管的数据范围,只是由于这些数据来自不同的流所以给Barrier设置了“分身”来监管,Barrier n-分身1监管的数据都到达了,可是我Barrier n-分身2的数据还没到,你就得等着我,咱们都到了,才能说明在这个算子上快照n完成了,不然你说这是n还是n-1,就乱套了。

接下来我们结合这张图和图中的例子说明一下情况。
在这里插入图片描述

某个算子收到来自多流输入的屏障对齐过程

我们仔细看一下这个过程。
在这里插入图片描述

  • 当operator接收到快照的屏障n后并不能直接处理之后的数据,而是需要等待其他输入快照的屏障n。否则话,将会将快照n的数据和快照n+1的数据混在一起。图中第一个所示,operator即将要收到数据流1(上面这个我们当成数据流1(6,5,4,3,2,1),下面的当成数据流2好了的屏障n,1,2,3在屏障n之后到达operator,这个时候如果数据流1的继续处理,那么operator中就会包含n屏障之后的数据(1,2,3),但是operator中此刻在接收和处理数据流2,数据(a,b,c)就会和数据流1中的(1,2,3)混合。

在这里插入图片描述

  • 快照n的数据流会被暂时放到一边。从这些数据流中获取到的数据不会被处理,而是存储到一个缓冲中。图中第一个所示,因为数据流2的屏障n还没到,所以operator持续接收1,2,3然而并不做任何处理。但是需要将1,2,3存入到buffer中。此时第二个数据流接到a,b,则直接发送,接到c发送c。

在这里插入图片描述

  • 一旦最后一个数据流收到了快照n,opertor就会将发出所有阻塞的数据,并发出自己的屏障。如图中第三个所示,operator最后收到了另一个数据流的屏障n,然后再发出a,b,c(图中operator中的c,b,a)以后,发出自己的屏障,这个时候buffer中又增加了一个4,变成(4,3,2,1)。

在这里插入图片描述

  • 之后operator会重新开始处理所有的输入数据流,先处理buffer中的数据,处理完之后再处理输入数据流的数据。如图第四个所示,先将buffer中的1,2,3,4先处理完,在接收并处理这两个数据源的数据。

送达语义

对多数据流进行校准会导致木桶原理,算子总体的处理效率取决于输入数据流里最慢的那个。通常校准会带来数毫秒的延迟,这在大多数情况下是可以接受的。然而一些对延迟特别敏感的应用可能比起数据的准确性更需要低延迟,因此 Flink 允许用户切换到非校准模式,但是这将会令作业的送达语义由准确一次降级到至少一次。

当校准步骤被跳过,即使收到某个输入数据流的 barrier n 算子也会继续工作。这样的话,属于第 n+1 个快照的数据也会被算到第 n 个快照窗口的算子状态里。当使用这个快照进行恢复时,这部分数据便会被重复计算,因为它们已经存在于快照的状态里,但 barrier n 以后的数据还会重流一遍。

另外,因为校准只作用于多输入或多输出的算子,对于单个输入/输出数据流的算子,即使用户将送达语义设置为至少一次,实际上还是准确一次。

也就是说,

  • 实现 EXACTLY ONCE 语义,Flink 通过一个 input buffer 将在对齐阶段收到的数据缓存起来,等对齐完成之后再进行处理。
  • 实现 AT LEAST ONCE 语义,无需缓存收集到的数据,会对后续直接处理,所以导致 restore 时,数据可能会被多次处理。

异步快照

我们上述虽然已经利用屏障使得每个算子在进行快照时不需要停止全部数据流,只需要当前算子停止工作然后进行快照即可,也即分布式快照。但是这样的屏障快照实际上仍是同步的,即在做快照的过程中算子会暂停处理新的数据,每次快照都会引入额外的数据延迟。实际上这是不必要的,快照可以完全交由后台异步实现,而实现这点算子必须可以提供一个状态对象,这个状态对象需要保证随后的修改不会影响当前的状态,比如 RockDB 的 copy-on-write 数据结构。完成这异步快照的对象称为 StateBackend(当然也可以是同步的,取决于具体实现),用户可以使用 Flink 内置的 StateBackend 或自定义。

状态后端已经对状态进行了持久化存储,一般不会在改变。

当从输入数据流收到快照屏障,算子开始异步拷贝当前的状态,它会立刻将屏障传至下游,并继续常规的工作。当后台的状态拷贝完成后,算子向 JobManager 确认快照成功。因为异步拷贝(1)存在丢失数据的风险且(2)不能保证顺序,因此作业快照成功的条件也随之改为所有 Sink 确认收到屏障加上所有有状态的算子都成功完成快照

保存点Savepoint

在这里插入图片描述
savePoint与checkPoint的区别

在这里插入图片描述

Flink中的checkpoint配置

Flink中默认是不开启checkpoint的,所以要开启需要进行配置。

开启检查点

env.enableCheckpointing(300);//周期性的触发检查点保存

* @param interval
*            Time interval between state checkpoints in millis.
* @param mode
*            The checkpointing mode, selecting between "exactly once" and "at least once" guaranteed.
 
public StreamExecutionEnvironment enableCheckpointing(long interval) {
	checkpointCfg.setCheckpointInterval(interval);
	return this;
}
public StreamExecutionEnvironment enableCheckpointing(long interval, CheckpointingMode mode) {
	checkpointCfg.setCheckpointingMode(mode);
	checkpointCfg.setCheckpointInterval(interval);
	return this;
}

通过流环境中的enableCheckpointing算子可以配置checkpoint的周期时间interval,也就是每300ms发送1次Barrier,默认是500ms;第2个可选参数mode为checkpoint的模式,分别为exactly onceat least once/

高级选项

 // 高级选项

// 设置checkpoint模式(2种)
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
//设置检查点的最大超时时间。
env.getCheckpointConfig().setCheckpointTimeout(60000L);
//设置同时允许存在检查点个数,也即流中的Barrier个数
env.getCheckpointConfig().setMaxConcurrentCheckpoints(2);
//设置2次checkpoint间的最小时间间隔,留出来用于算子执行计算,否则有可能会一直执行checkpoint。
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(100L);
//设置true优先从检查点中恢复而不是更近的保存点,默认false
env.getCheckpointConfig().setPreferCheckpointForRecovery(true);
//设置容忍checkpoint的失败次数,0代表检查点配置失败也算任务失败
env.getCheckpointConfig().setTolerableCheckpointFailureNumber(0);
// 任务流取消和故障时会保留Checkpoint数据,以便根据实际需要恢复到指定的Checkpoint
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);

enableExternalizedCheckpoints中的参数。

  • ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION: 取消作业时保留检查点。请注意,在这种情况下,您必须在取消后手动清理检查点状态。
  • ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION: 取消作业时删除检查点。只有在作业失败时,检查点状态才可用。

重启策略

// 3. 重启策略配置

// 固定延迟重启  每隔10秒钟尝试重启,尝试3次,起不来就报错
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, 10000L));
// 失败率重启  在10分钟内重启3次,每次间隔1分钟,起不来就报错
env.setRestartStrategy(RestartStrategies.failureRateRestart(3, Time.minutes(10), Time.minutes(1)));

除以上2种以外还没有其他RestartStrategies重启策略,可以在IDEA查看RestartStrategies的函数,就不一一介绍了。

参考资料

《Apache Flink 进阶(三):Checkpoint 原理解析与应用实践》

《Flink 轻量级异步快照 ABS 实现原理》

《Flink 容错性机制- 屏障(barrier)实现原理》

《flink超越Spark的Checkpoint机制 》

《Flink状态管理与CheckPoint》

《Flink–Checkpoint机制原理》

《Flink的checkpoint的流程梳理》

《Flink CheckPoint详细过程》

《Flink-容错机制 | 一致性检查点 | 检查点到恢复状态过程 | Flink检查点算法(Chandy-Lamport) | 算法操作解析 | 保存点简介》

《Flink 专题 -2Checkpoint、Savepoint 机制》

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值