10. Flink 容错机制概述

10. Flink 容错机制概述

10.1 为什么要容错机制

Flink是一个stateful(带状态)的数据处理系统,系统在处理数据的过程中,各算子所记录的状态会随着数据的处理而不断变化;
一旦系统崩溃,需要重启后能恢复出崩溃前的状态才能进行数据的接续处理,因此,必须要有一种机制能对系统内的各种状态进行持久化容错;

10.2 Flink的Exactly-Once概述

10.2.1 EOS基本概念

Exactly-Once语义:指端到端的一致性,从数据读取、引擎计算、写入外部存储的整个过程中,即使机器或软件出现故障,都确保数据仅处理一次,不会重复也不会丢失。

对于Flink程序来说,端到端EOS语义则包含source、state、sink三个环节的紧密配合

10.2.2 Flink的精确一致核心要素

Flink图36

要实现端到端的EOS保证,核心点在于:
一条(或者一批)数据,从注入系统、中间处理、到输出结果的整个流程中,要么每个环节都处理成功,要么失败回滚(回到从未处理过的状态)!

Flink在目前的各类分布式计算引擎中,对EOS的支持是最完善的;
在合理的数据源选择,合理的算子选择,合理的目标存储系统选择,合适的参数配置下,可以实现严格意义上的端到端EOS

source端的保证

数据从上游进入Flink,必须保证消息严格一次消费,同时Source端必须满足可重放(replay),否则Flink计算层收到消息后未计算,却发生failure而重启,消息就会丢失。

Flink的很多source算子都能为EOS提供保障,如kafka Source:

  • 能够记录偏移量
  • 能够重放数据
  • 将偏移量记录在state中,与下游的其它算子的state一起,经由checkpoint机制实现了状态数据的快照统一
Flink算子状态的精确一次保证

利用checkpoint机制,把状态数据定期持久化存储下来,Flink程序一旦发生故障的时候,还可以选择状态点恢复,避免数据的重复,丢失。

  • barrier对齐的checkpoint(可支持exactly-once)
  • barrier非对齐的checkpoint(只能实现at least once)

基于分布式快照算法:(Chandy-Lamport),Flink实现了整个数据流中各算子的状态数据快照统一;
++即一次checkpoint后所持久化的各算子的状态数据,确保是经过了相同数据的影响++
这样一来,就能确保:

  • 一条(或一批)数据要么是经过了完整正确处理
  • 如果这条(批)数据在中间任何过程失败,则重启恢复后,所有算子的state数据都能回到这条数据从未处理过时的状态
Sink端的保证

Flink将处理完的数据发送到Sink端时,通过两阶段提交协议,即TwoPhaseCommitSinkFunction函数。该SinkFunction提取并封装了两阶段提交协议中的公共逻辑,保证Flink发送Sink端时实现严格一次处理语义,同时,Sink端必须支持事务机制,能够支持数据回滚或者满足幂等性。
回滚机制:即当作业失败后,能够将部分写入的结果回滚到之前写入的状态。
幂等性:就是一个相同的操作,无论重复多少次,造成的结果和只操作一次相等。即当作业失败后,写入部分结果,但是当重新写入全部结果时,不会带来负面结果,重复写入不会带来错误结果。

从前文所述的source端和内部state的容错机制来看,一批数据如果在sink端写出过程中失败(可能已经有一部分数据进入目标存储系统),则重启后重放这批数据时有可能造成目标存储系统中出现数据重复,从而破坏EOS;

对此,Flink也设计了相应机制来确保EOS

  • 采用幂等写入方式
  • 采用两阶段提交(2PC,two phase)写入方式
  • 采用预写日志提交方式
Sink幂等性

满足幂等性写入特性的sink,可以支持端到端一致性;
但是在写入过程中可能会存在短暂不一致;

两阶段事务提交(2PC)

++两阶段事务支持++
此方式实现端到端一致性利用的是目标存储系统的事务机制;
sink会在checkpoint前对目标存储系统开启事务,并进行数据预提交;
等到checkpoint完成时,再对目标存储系统提交事务,从而物化结果;
如果在checkpoint前任务失败,则此前开启的事务及预提交数据,会被目标存储系统的事务机制回滚;
++预写日志两阶段提交++