1. 检查点(Checkpoint)
flink将之前某个时间点所有的状态保存下来,这份存档就是所谓的检查点(checkpoint)。检查点是 Flink 容错机制的核心。检查是针对故障恢复的结果而言的:故障恢复之后继续处理的结果,应该与发生故障前完全一致。所以有时又会把 checkpoint 叫作一致性检查点
1.1 检查点的保存
(1) 周期性的触发保存
检查点作为应用状态的一份存档,其实就是所有任务状态在同一时间点的一个快照(snapshot),它的触发是周期性的。每隔一段时间检查点保存操作被触发时,就把每个任务当前的状态复制一份,按照一定的逻辑结构放在一起持久化保存起来,就构成了检查点
(2) 保存的时间点
当所有任务都恰好处理完一个相同的输入数据的时候,将它们的状态保存下来。首先,这样避免了除状态之外其他额外信息的存储,提高了检查点保存的效率。其次,一个数据要么就是被所有任务完整地处理完,状态得到了保存;要么就是没处理完,状态全部没保存:这就相当于构建一个事务(transaction)。如果出现故障,恢复到之前保存的状态,故障时正在处理的所有数据都需要重新处理;所以只需要让源(source)任务向数据源重新提交偏移量、请求重放数据就可以了。这需要源任务可以把偏移量作为算子状态保存下来,而且外部数据源能够重置偏移量;(典型应用 Kafka)
1.2 从检查点恢复状态
当发生故障时,需要找到最近一次成功保存的检查点来恢复状态

具体的步骤为:
(1)重启应用
遇到故障之后,第一步当然是重启,所有任务的状态会清空

(2)读取检查点,重置状态
找到最近一次保存的检查点,从中读出每个算子任务状态的快照,分别填充到对应的状态中。这样,Flink 内部所有任务的状态,就恢复到了保存检查点的那一时刻

(3)重放数据
从检查点恢复状态后如果直接继续处理数据,那么保存检查点之后、到发生故障这段时间内的数据就相当于丢掉了;这会造成计算结果的错误。为了不丢数据,应该从保存检查点后开始重新读取数据,这可以通过 Source 任务向外部数据源重新提交偏移量(offset)来实现。这样,整个系统的状态已经完全回退到了检查点保存完成的那一时刻

(4)继续处理数据

注:
想要正确地从检查点中读取并恢复状态,必须知道每个算子任务状态的类型和先后顺序(拓扑结构);因此为了可以从之前的检查点中恢复状态,在改动程序、修复 bug 时要保证状态的拓扑顺序和类型不变。状态的拓扑结构在 JobManager 上可以由 JobGraph 分析得到,而检查点保存的定期触发也是由 JobManager 控制的;所以故障恢复的过程需要 JobManager 的参与
1.3 检查点算法
在不暂停整体流处理的前提下,将状态备份保存到检查点。在 Flink中,采用了基于 Chandy-Lamport 算法的分布式快照
(1)检查点分界线(Barrier)
借鉴水位线(watermark)的设计,在数据流中插入一个特殊的数据结构,专门用来表示触发检查点保存的时间点。收到保存检查点的指令后,Source 任务可以在当前数据流中插入这个结构;之后的所有任务只要遇到它就开始对状态做持久化快照保存。由于数据流是保持顺序依次处理的,因此遇到这个标识就代表之前的数据都处理完了,可以保存一个检查点;而在它之后的数据,引起的状态改变就不会体现在这个检查点中,而需要保存到下一个检查点。这种特殊的数据形式,把一条流上的数据按照不同的检查点分隔开,所以就叫作检查点的分界线(Checkpoint Barrier)。检查点分界线中带有一个检查点 ID,这是当前要保存的检查点的唯一标识

在 JobManager 中有一个检查点协调器(checkpoint coordinator),专门用来协调处理检查点的相关工作。检查点协调器会定期向 TaskManager 发出指令,要求保存检查点(带着检查点 ID);TaskManager 会让所有的 Source 任务把自己的偏移量(算子状态)保存起来,并将带有检查点 ID 的分界线(barrier)插入到当前的数据流中,然后像正常的数据一样像下游传递;之后 Source 任务就可以继续读入新的数据了。每个算子任务只要处理到这个 barrier,就把当前的状态进行快照

本文详细介绍了Flink中的检查点机制,包括周期性保存、从检查点恢复状态的步骤以及检查点算法。此外,还讨论了状态一致性的重要性,包括至少一次、最多一次和精确一次三种级别,以及如何实现端到端精确一次的一致性。最后,提到了保存点的概念,它是检查点的扩展,用于作业的灵活重启。
最低0.47元/天 解锁文章
267

被折叠的 条评论
为什么被折叠?



