【Flink】容错机制

目录

1、检查点

​编辑1.1 检查点的保存

1.1.1 周期性的触发保存

1.1.2 保存的时间点

1.1.3 时间点的保存与恢复

1.1.3.1保存

​编辑

1.1.3.2 恢复的具体步骤:

1.2 检查点算法

1.2.1 检查点分界线(Barrier)

1.2.2 分布式快照算法(Barrier对齐的精准一次)

1.2.3 分布式快照算法(Barrier对齐的至少一次)

1.2.4 分布式快照算法(非Barrier对齐的精准一次)

1.3检查点配置

1.3.1启用检查点  

1.3.2检查点存储

1.3.3其它高级配置

1.3.3.1常用高级配置

1.3.4通用增量 checkpoint (changelog)

1.3.5最终检查点

1.5保存点

1.5.1保存点的用途

1.5.2使用保存点

1.5.2.1 创建保存点

1.5.2.2从保存点重启应用

1.5.3 使用保存点切换状态后端

1.5.3.1 提交flink作业

1.5.3.2 停止flink作业时,触发保存点

1.5.3.3 从savepoint恢复作业,同时修改状态后端

1.5.3.4 从保存下来的checkpoint恢复作业

2、状态一致性

2.1 一致性的概念和级别

2.2 端到端的状态一致性

3、端到端精确一次

3.1 输入端保证

3.2 输出端保证

3.2.1幂等(Idempotent)写入

3.2.1.1预写日志(write-ahead-log,WAL)

3.2.1.2两阶段提交(two-phase-commit,2PC)

3.3 Flink和Kafka连接时的精确一次保证

3.3.1整体介绍

        3.3.1.1 Flink内部

        3.3.1.2输入端

        3.3.1.3输出端

3.3.2需要的配置


在Flink中,有一套完整的容错机制来保证故障后的恢复,其中最重要的就是检查点

1、检查点

        在流处理中,我们可以用存档读档的思路,将之前某个时间点的所有状态保存下来,这份“存档”就是所谓的“检查点”。

        这里所谓的检查,是针对故障恢复结果而言的:故障恢复之后继续处理的结果,应该与发生故障之前完全一致,我们需要检查结果的正确性,所以有时又会把checkpoint叫做“一致性检查点”。

1.1 检查点的保存

1.1.1 周期性的触发保存

        “随时存档”确实恢复起来方便,可是需要我们不停地做存档操作。如果每处理一条数据就进行检查点的保存,当大量数据同时到来时,就会耗费很多资源来频繁做检查点,数据处理的速度就会受到影响。所以在Flink中,检查点的保存是周期性触发的,间隔时间可以进行设置。

1.1.2 保存的时间点

        我们应该在所有任务(算子)都恰好处理完一个相同的输入数据的时候,将它们的状态保存下来。这样做可以实现一个数据被所有任务(算子)完整地处理完,状态得到了保存。

        如果出现故障,我们恢复到之前保存的状态,故障时正在处理的所有数据都需要重新处理;我们只需要让源(source)任务向数据源重新提交偏移量、请求重放数据就可以了。当然这需要源任务可以把偏移量作为算子状态保存下来,而且外部数据源能够重置偏移量;kafka就是满足这些要求的一个最好的例子。

1.1.3 时间点的保存与恢复

1.1.3.1保存

当我们需要保存检查点时,就是在所有任务处理完同一条数据后,对状态做一个快照保存下来。

故障异常:

1.1.3.2 恢复的具体步骤:
  1. 遇到故障之后,第一步重启,重启后,所有任务的状态会清空
  2. 读取检查点,重置状态
    1. 找到最近一次保存的检查点,从中读取每个算子任务状态的快照
  3. 重置偏移量
    1. 为了保证不丢数据,我们应该从保存检查点后开始重新读取数据,可以通过source任务向外部数据源重新提交偏移量(offset)来实现

1.2 检查点算法

        在Flink中,采用了基于Chandy-Lamport算法的分布式快照,可以在不暂停整体流处理的前提下,将状态备份保存到检查点。

1.2.1 检查点分界线(Barrier)

        借鉴水位线的设计,在数据流中插入一个特殊的数据结构,专门用来表示触发检查点保存的时间点。收到保存检查点的指令后,Source任务可以在当前数据流中插入这个结构;之后的所有任务只要遇到它就开始对状态做持久化快照保存。由于数据流是保持顺序依次处理的,因此遇到这个标识就代表之前的数据都处理完了,可以保存一个检查点;而在它之后的数据,引起的状态改变就不会体现在这个检查点中,而需要保存到下一个检查点。

        这种特殊的数据形式,把一条流上的数据按照不同的检查点分隔开,所以就叫做检查点的“分界线”(Checkpoint Barrier)。

1.2.2 分布式快照算法(Barrier对齐的精准一次)

        watermark指示的是“之前的数据全部到齐了”,而barrier指示的是“之前所有数据的状态更改保存入当前检查点”:它们都是一个“截止时间”的标志。所以在处理多个分区的传递时,也要以是否还会有数据到来作为一个判断标准。

        具体实现上,Flink使用了Chandy-Lamport算法的一种变体,被称为“异步分界线快照”算法。算法的核心就是两个原则:

  •         当上游任务向多个并行下游任务发送barrier时,需要广播出去;
  1.         而当多个上游任务向同一个下游任务传递分界线时,需要在下游任务执行“分界线对齐”操作,也就是需要等到所有并行分区的barrier都到齐,才可以开始状态的保存。
  • 场景举例:

设置算子并行度为2。

设置2个source任务,会分别读取2个数据流(或者一个源的不同分区)。

检查点保存算法的具体过程:

(1)触发检查点:JobManager向Source发送Barrier;

(2)Barrier发送:向下游广播发送;

(3)Barrier对齐:下游需要收到上游所有并行度传递过来的Barrier才做自身状态的保存;

(4)状态保存:有状态的算子将状态保存至持久化。

(5)先处理缓存数据,然后正常继续处理

        (补充)由于分界线对齐要求先到达的分区做缓存等待,一定程度上会影响处理的速度;当出现背压时,下游任务会堆积大量的缓冲数据,检查点可能需要很久才可以保存完毕。

        为了应对这种场景,Barrier对齐中提供了至少一次语义以及Flink 1.11之后提供了不对齐的检查点保存方式,可以将未处理的缓冲数据也保存进检查点。这样,当我们遇到一个分区barrier时就不需等待对齐,而是可以直接启动状态的保存了。

1.2.3 分布式快照算法(Barrier对齐的至少一次)

  •  JobManager发送指令,触发检查点保存;source任务中插入一条分界线,并将偏移量保存到远程的持久化存储中。
  •  状态快照保存完成,分界线向下游传递

        状态存入持久化存储之后,会返回通知给Source任务;Source任务就会向JobManager确认检查点完成,然后跟数据一样把分界线向下游任务传递。

        说明:由于Source和Map之间是一对一(forward)的传输关系(这里没有考虑算子链),所以barrier可以直接传递给对应的Map任务之后Source任务就可以继续读取新的数据了。与此同时,SumI已经将第二条流传来的(hello,1)处理完毕,更新了状态

  • 向下游多个并行子任务广播分界线,执行分界线对齐

        Map任务没有状态,所以直接将barrier?继续向下游传递。这时由于进行了keyBy分区,所以需要将barrier)广播到下游并行的两个Sum
任务。同时,Sum任务可能收到来自上游两个并行Map任务的barrier,所以需要执行“分界线对齐”操作。

         而Sum1只收到了来自Map2的barrier,所以这时需要等待分界线对齐。而如果分界线己经到达的分区任务Map2又传来数据,直接计算等到下一个Barrier到达时做状态的保存。重新启动时介于两个Barrier.之间分界线己经到达的分区任务Map2传过来的数据会再次计算(至少一次)

  • 分界线对齐后,保存状态到持久化存储

        

        各个分区的分界线都对齐后,就可以对当前状态做快照,保存到持久化存储了。存储完成之后,同样将barrierl向下游继续传递,并通知JobManager保存完毕。

        这个过程中,每个任务保存自己的状态都是相对独立的,互不影响。我们可以看到,当Sum将当前状态保存完毕时,Source1任务
已经读取到第一条流的第五个数据了。

1.2.4 分布式快照算法(非Barrier对齐的精准一次)

  • JobManager发送指令,触发检查点的保存;Source任务中插入一个分界线,并将偏移量保存到远程的持久化存储中。

        

        说明:并行的Source任务保存的状态为3和1,表示当前的1号检查点应该包含:第一条流中截至第三个数据、第二条流中截至第一个数据的所有状态更改。可以发现Source任务做这些的时候并不影响后面任务的处理,Sum2已经处理完了第一条流中传来(world,l)对应的状态也有了更改。

  • 状态快照保存完成,分界线向下游传递

       

         状态存入持久化存储之后,会返回通知给Source任务;Source任务就会向JobManager确认检查点完成,然后跟数据一样把分界线向下游任务传递。

        说明:由于Source和Map之间是一对一(forward)的传输关系(这里没有考虑算子链),所以barrier可以直接传递给对应的Map任务。之后Source任务就可以继续读取新的数据了。与此同时,Sum1已经将第二条流传来的(hello,1)处理完毕并更新了状态。

  • 向下游多个并行子任务广播分界线,执行非Barrier对齐

        

        Map任务没有状态,所以直接将barrier继续向下游传递。这时由于进行了keyBy分区,所以需要将barrier广播到下游并行的两个Sum任务。同时,Sum任务可能收到来自上游两个并行Map任务的barrier,执行“非Barrier对齐”操作。

        这里我们我只关注Sum1的细节,Sum1在第一个barrier到达时就开始执行非对齐检查点。

  • 向下游多个并行子任务广播分界线,执行非Barrier对齐

       

         核心思想只要in-fight的数据也存到状态里,barrier就可以越过所有in-flight的数据继续往下游传递。

此时的Sum1任务在第一个Barrier到达输入缓冲区时:

        ①直接将barrier放到输出缓冲区末端,向下游传递。

        ②标记数据(图中标颜色部分)

                一是被第一个barrier越过的输入缓冲区和输出缓冲区的数据

                二是在其他barrier之前的所有数据

        ③把标记数据和状态一起保存到checkpoint中,从checkpoint恢复时这些数据也会一起恢复到对应位置

1.3检查点配置

        检查点的作用是为了故障恢复,我们不能因为保存检查点占据了大量时间、导致数据处理性能明显降低。为了兼顾容错性和处理性能,我们可以在代码中对检查点进行各种配置。

1.3.1启用检查点  <

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lxtx-0510

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值