《Flink 架构》系列(已完结),共包含以下 6 篇文章:
如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 吧 (点赞 、关注 、收藏 )!!!您的支持 将激励 博主输出更多优质内容!!!
Flink 的故障恢复算法是基于 状态的检查点 来完成的。检查点会周期性地生成,而且会根据配置的策略自动丢弃。检查点的目的是保证应用在出现故障的时候可以顺利重启,因此当应用被手动停止后,检查点也会随之删除(可以通过配置让应用在取消的时候 保留最近一次检查点)。但除了用于故障恢复,应用的一致性快照还有很多其他用途。
Flink 最具价值且独具一格的功能之一是 保存点。原则上,保存点的生成算法和检查点完全一样,因此可以把保存点看做包含一些额外元数据的检查点。保存点的生成不是由 Flink 自动完成,而是需要由用户(或外部调度器)显式触发。同时,Flink 也不会自动清理保存点。后续我们将介绍如何生成和删除保存点。
给定一个应用和一个兼容的保存点,我们可以从该保存点启动应用。这样就能用保存点内的数据初始化状态并从生成保存点的那一刻继续运行应用。这个行为看上去和利用检查点将应用从故障中恢复完全一致,但其实故障恢复只是一种特殊情况,它会在完全相同的集群上,以完全相同的配置,运行完全相同的应用。而将应用从某个保存点启动还能让你做更多事情。
保存点的功能如此强大,以至于很多用户都会 周期性地创建保存点,从而可以及时 “回到过去”。我们在生态中见到保存点最有趣的应用之一是不断将流式应用迁移到实例价格最低的数据中心。
所有之前提到的保存点相关用例都遵循同一个模式。首先为正在运行的应用生成一个保存点,然后在应用启动时用它去初始化状态。本节我们将介绍 Flink 在从保存点启动时如何去初始化应用状态。
每个应用都会包含很多算子,而每个算子又可以定义一个或多个的键值或算子状态。算子会在一个或多个任务上并行执行,因此一个典型的应用会包含多个状态,它们分布在不同 TaskManager 进程内的算子任务上。
下图所展示的应用包含了三个算子,每个算子各有两个任务。其中一个算子(OP-1
)有一个算子状态(OS-1
),另一个算子(OP-2
)有两个键值分区状态(KS-1
和 KS-2
)。在生成保存点的时候,所有任务的状态都会拷贝到某个持久化存储位置上。
保存点中的状态副本会按照 算子标识 和 状态名 称进行组织。该算子标识和状态名需要能将保存点的状态数据映射到应用启动后的算子状态上。当应用从保存点启动时、Flink 会将保存点的数据分发到对应算子的任务上。
❗ 注意:保存点没有包含 算子任务 的相关信息。这是因为任务数目可能会随着应用启动时所指定的并行度而改变。我们已经在之前的博客中讨论过 Flink 对于有状态算子的扩缩容策略。
如果应用在从保存点启动的时候发生过改动,那么保存点中的状态只有在应用还保留着那些含有对应标识和状态名称的算子时才可以成功映射。默认情况下,Flink 会给每个算子分配一个唯一标识。但该标识是根据前置算子的标识按照某种确定规则生成的。这意味着任何一个前置算子发生改变(例如添加或删除某个算子)都会导致该标识发生变化。因此使用默认算子标识的应用如果不想丢失状态,那么改动空间会比较有限。所以我们强烈建议手工指定算子标识,而不要依赖 Flink 的默认分配机制。有关分配算子标识的详细内容会在后续有关 “指定唯一算子标识” 的博客中介绍。