Flink 容错机制

Flink 容错机制

状态的一致性:

  • 故障处理成功之后恢复的数据与之前的数据相比的正确程度。
  • 一致性级别:
    1. 'at-most-once'>最多一次,恢复之后可能会数据丢失。
    2. 'at-least-once'>至少一次,恢复之后可能会重复计算。
    3. 'exactly-once'>精准一次,故障后得到的计数结果与正确值一致。

端到端的一致性:

端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用,每个组件都保证自己的一致性,整体一致性取决于一致性最弱的组件。

  • Source端:需要外部源可重设数据读取位置,保证故障时可以重新读取数据。

  • Flink内部:依赖CheckPoint机制。

  • Sink端:需要保证故障恢复时,数据不会重复写入外部系统。有两种实现方式:幂等写入或事务性写入。

    幂等写入:单次操作可以重复执行,但结果只会更改一次,重复后执行操作不起作用。

    事务性写入:需要构建事务来写入外部系统,构建事务对应Checkpoint,等到Checkpoint真正完成才将所有结果写入外Sink系统。有两种实现方式,预写日志、两阶段提交。

    1. 预写日志 WAl> 将要写出的数据先存储在Flink内存中,之后一次性写出,如果写出失败则再写出一次。
    2. 两阶段提交 2PC> 第一阶段每个节点都提交自己的事务,待所有节点都完成之后第二阶段整体正式提交,任意一个阶段没完成整个任务失败,所有节点会撤回已提交事务。

    Sink到文件系统如何实现两阶段提交?
    1.写出到一个临时文件 -> 预提交。
    2.写临时文件成功就把临时文件改名为正式文件名 -> 正式提交。
    3.如果预提交中出现失败就删除临时文件 -> 回滚。

Checkpoint原理:

Flink通过Checkpoint机制保证'exactly-once',在出现故障时将系统重置回正确状态。

  • 实现原理:每隔固定的时间,对当前状态进行一次快照,出现故障时能够将整个应用流图的状态恢复到故障之前的某一状态,保证应用流图状态的一致性。

  • 快照的实现算法:所有的Task执行完相同的处理时。

    1. 简单算法-暂停应用,然后开始做检查点,再重新恢复应用。需要停止服务不好。

    2. 异步分界线快照::轻量级、速度快。采用昌迪兰伯特算法(分布式快照)的一种变体。每个需要Checkpoint的应用启动时,Flink的JobManager都会为其创建一个CheckpointCoordinator用来全权负责本应用的快照制作。

      说明:Checkpoint默认重启次数为Integer的最大值,默认1s一次。

  • Barrier:是一种特殊的数据,插入到数据流后作为数据流的一部分随着数据流动,但始终不会跨越流中的数据,也不会暂停数据的流动。每个Barrier会将数据分为两部分,Barrier之前的进入当前快照,之后的进入下一个快照,并且每个Barrier都携带快照ID,同一时刻可以有来自多个不同快照的Barrier。

    1. Barrier对齐:精准一次,多并行度下某个算子在等待上游所有barrier时,其他数据过来了不处理,会将数据放入缓冲区等待。
    2. Barrier不对齐:至少一次,某个算子在等待上游所有barrier的过程中对其他过来的数据仍然进行处理。这种方式可能会导致数据的重复计算,故障时按照最小的barrier进行恢复。
  • Flink背压:

    Flink的信用机制credit,每个算子前后都有一个输入缓冲和输出缓冲,采用barrier对齐的方式,当前算子在等待上游的barrier时,上游算子的输出数据会进入到当前算子的输入缓冲区,当某个上游的barrier迟迟不来时会导致当前算子的输入缓冲区积攒大量的数据造成堵塞,此时上游算子的输出数据无法发送至下游算子,同时该算子还不停的接收数据,这会导致上游算子的输出缓冲也堵塞,最终会使Sink算子的输入缓冲区也堵塞从而导致Sink无法读取数据,从后向前逐级堵塞。

  • 检查点制作过程(2PC):

    JobManager内部的一个协调器CheckpointCoordinator向所有Source节点触发Checkpoint,并周期性的生成barrier插入到Source端的数据流中。Source节点向下游广播barrier,只有下游task收到所有上游传递的barrier时才执行相应的Checkpoint触发当前task的备份,并将自身的状态的异步的写入持久化存储中,多并行度时要选择barrier对齐方式,只有barrier对齐才能保证checkpoint精准一次性消费,而barrier不对齐的方式可能会重复计算,导致故障恢复后结算结果不准确。每个task状态备份完成后,会将备份数据的地址Statehandle通知给CheckpointCoodirnator,当下游的Sink节点接收到所有上游的barrier时,会执行本地快照,采用RocksDBStateBackend状态后端,先将全量数据刷写到磁盘上,然后Flink会从中选择没有上传的文件进行持久化备份。Sink完成Checkpoint之后会将Statehandle返回给Coordinator,本条数据开启本次事务,待下一批数据来了时候开启下一次事务,然后预提交作业(第一阶段),数据写入Kafka日志分区但标记为未提交,同时Sink会开启一个新的事务用于提交下个检查点的数据。当CheckpointCoordinator在Checkpoint设定的超时时间内收集到所有task的Statehandle则认为本次Checkpoint全局完成,之后会将自己的CheckpointMeta持久化备份,然后会向所有task发送checkpoint已完成的通知,Sink收到checkpoint完成通知后会正式提交(第二阶段)。然后外部Kafka关闭事务,提交的本条数据就可以正常消费。如果在规定时间内没有收集完则认为本次Checkpoint失败,会删除这次Checkpoint产生的所有状态数据。

    ***说明:两阶段提交设置CheckPoint的超时时间和Kafka事务的超时时间是时Kafka事务的超时时间必须比CheckPoint的超时时间大,否则CheckPoint成功时事务可能失败,而事务失败关闭后无法提交事务,虽然此时CheckPoint已经完成,但实际上并没有被提交,会导致已经Checkpoint的这部分数据丢失。

SavePoint:

Flink还提供了可以自定义的镜像保存功能,就是保存点。
保存点于检查点使用的算法完全相同,因此保存点可以认为是具有一些元数据的检查点,但是Flink不会自己创建保存点,需要用户明确的触发创建操作,保存点可以用于故障恢复、有计划的手动备份,更新程序应用、版本变迁等。
说明:保存点故障恢复的时候需要先设置保存点,然后从之前保存的保存点恢复数据,提交任务时添加 -S + 保存点路径参数即可。

posted @ 2021-06-01 16:46  yuexiuping  阅读(304)  评论(0编辑  收藏  举报