03-Flink 容错和消息传递语义
Flink 是如何做容错的?(重要,面试很频繁)
在使用了 Flink 的状态管理之后,因为此时所有的 state 的读写都只是在 task 本地的内存中(默认,现在只讨论内存的情况)进行,也就是 state 数据此时只存储在内存中。假设当任务出现故障之后,这些在内存中的 state 数据也会丢失,就无法恢复了。所以需要一种机制来保障这些 state 数据的不丢失,这也就是容错机制。
Flink 通过 checkpoint 来实现。Flink 开启了 checkpoint 之后,会定时将状态数据的快照持久存储到指定的 statebackend,通常是 HDFS。
Flink 定期对整个 job 任务进行快照,将快照产生的备份数据保存到指定的 statebacked 中。当出现故障时,将 job 的状态恢复到最近的一个快照点。
Flink 的容错机制的核心部分是生成分布式数据流和 operator 状态一致的快照。这些快照充当 checkpoint(检查点), 系统可以在发生故障时将其回滚。分布式快照是由 Chandy-Lamport 算法实现的。
每个 checkpoint 由 checkpoint ID 和 timestamp 来唯一标识,其中 checkpoint ID 可以是 standalone(基于内存,保存在 JobManager 内存中)的,也可能是基于 ZK 的。
Flink 实现容错主要靠强大的 CheckPoint 机制和 State 机制。Checkpoint 负责定时制作分布式快照、对程序中的状态进行备份;State 用来存储计算过程中的中间状态。
Flink 分布式快照的原理是什么?
Flink 的分布式快照是根据 Chandy-Lamport 算法量身定做的。简单来说就是持续创建分布式数据流及其状态的一致快照。
核心思想是在 input source 端插入 barrier,控制 barrier 的同步来实现 snapshot 的备份和 exactly-once 语义。
Flink 是如何保证 Exactly-once 语义的
Flink 通过实现两阶段提交和状态保存来实现端到端的一致性语义。分为以下几个步骤:
- 开始事务(beginTransaction):创建一个临时文件夹,来把数据写入到这个文件夹里面。
- 预提交(preCommit):将内存中缓存的数据写入文件并关闭。
- 正式提交(commit):将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些延迟。
- 丢弃(abort)丢弃临时文件。
若失败发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可删除预提交的数据。