Apache Flink数据流的Fault Tolerance机制

简介

Apache Flink提供了一个失败恢复机制来使得数据流应用可以持续得恢复状态。这个机制可以保证即使线上环境的失败,程序的状态也将能保证数据流达到exactly once的一致性。注意这里也可以选择降级到保证at least once的一致性级别。

失败恢复机制持续地构建分布式流式数据的快照。对于那些只有少量状态的流处理应用,这些快照都是非常轻量级的并且可以以非常频繁的频率来构建快照而不需要太多地考虑性能问题。而流应用的状态被存储在一个可配置的持久化存储(比如master节点或者HDFS)。

在程序失败的情况下(比如由于机器、网络或者软件失败),Flink将停止分布式流处理。系统将重启operator并且将他们重置为最新成功了的检查点。输入流会被重置为状态快照点。任何被重启的并发数据流处理的记录,可以得到的保证是:他们不可能是检查点之前的记录。

注意:对于该机制,为了达到完整的保证,数据流source(例如message queue或者message broker)需要具备回退到最近定义的还原点的能力。Apache Kafka具备这样的能力并且Flink的Kafka连接器利用了这个能力。

因为Flink的检查点是通过分布式快照实现的,所以这里我们对快照和检查点不进行区分。

检查点

Flink的失败恢复机制最核心的部分是持续得构建分布式流处理和operator状态的快照。这些快照可以看作持续的检查点,如果发生失败的情况,系统可以从这些点进行恢复。Flink构建这些快照的机制可以被描述成分布式数据流的轻量级异步快照。它已经被实现为标准的Chandy-Lamport算法了,并用来实现分布式快照,而且几乎是为Flink的执行模型量身定做的。

屏障

Barriers:此处统一称为屏障也可称之为栅栏

在Flink的分布式快照机制中有一个核心的元素是流屏障。屏障作为数据流的一部分随着记录被注入到数据流中。屏障永远不会赶超通常的流记录,它会严格遵循顺序。屏障将数据流中的记录隔离成一系列的记录集合,并将一些集合中的数据加入到当前的快照中,而另一些数据加入到下一个快照中。每一个屏障携带着快照的ID,快照记录着ID并且将其放在快照数据的前面。屏障不会中断流处理,因此非常轻量级。来自不同快照的多个屏障可能同时出现在流中,这意味着多个快照可能并发地发生。

stream source中,流屏障被注入到并发数据流中。快照n被注入屏障的点(简称为Sn),是在source stream中的数据已被纳入该快照后的位置。例如,在Apache Kafka中,该位置将会是partition中最后一条记录的offset。这个Sn的位置将被报告给检查点协调器Flink JobManager)。

屏障接下来会流向下游。当一个中间的operator从所有它的输入流中接收到一个来自快照n的屏障,它自身发射一个针对快照n的屏障到所有它的输出流。一旦一个sink operator(流DAG的终点)从它所有的输入流中接收到屏障n,它将会像检查点协调器应答快照n。在所有的sink应答该快照后,它才被认为是完成了。

当快照n完成后,可以认为在Sn之前的记录没有必要再从source中流入,因为这些记录已经穿过了整个数据流的处理拓扑。

那些不止一个输入流的的operator需要在快照屏障上对齐(align)输入流。上面的插图说明了这一点:

  • 一旦operator从外来流中收到快照屏障n,它就不能处理该流中更多的记录直到它从其他输入中接收到屏障n。否则,会混合属于快照n以及快照n+1的记录
  • 汇报过屏障n的流会被临时搁置到一边,从这些流中继续接收到的记录并没有被处理,而是被放进一个输入缓冲区中
  • 一旦最后一个流接收到屏障n,operator发射所有待处理的需要流出的记录,然后发射快照n屏障本身
  • 此后,operator恢复从所有输入流的记录的处理,在处理来自流的记录之前先处理来自输入缓冲区的记录

状态

无论operator包含任何形式的状态,这些状态必须是快照的一部分。operator状态有不同的形式:

  • 用户定义的状态:这种类型的状态通过transformation函数(比如map()或者filter())直接创建和修改。用户定义的状态可以是一个简单的变量或者跟某个函数关联的key/value状态。
  • 系统状态:这种状态通常关系到数据缓冲区,它们是operator计算逻辑的一部分。这种状态的一个典型的例子是window buffers,在它内部,系统为其收集(以及聚合)记录直到窗口被计算。

operator在从它们的所有输入流中收到所有的快照屏障时,在发射屏障到它们的输出流之前会对状态做快照。在那个点,所有在屏障之前的记录的状态更新必须完成,并且在屏障之后依赖于记录的更新不会被接收。因为快照的状态有可能会非常大,它们被存储在可配置的状态终端上。默认存储的位置是JobManager的内存,但为了严谨,应该配置一个分布式的可靠的存储层(比如HDFS)。在状态被存储之后,operator会应答检查点,发射快照屏障到输出流并继续处理流程。

现在快照的结果包含:

  • 对每个并行流的数据源而言,快照开始时的偏移量或者位置
  • 对每个operator而言,一个指针指向存储在快照中的状态部分

恰好一次VS至少一次

对齐步骤可能会增加流处理的延迟。通常这个额外的延迟被控制在毫秒级,但我们也看到一些场景下,延迟显著增加。对于那些要求针对所有记录的处理始终保持低延迟的应用(比如几毫秒),Flink提供了一个开关(选项)可以在检查点中跳过流对齐。检查点快照仍然被构建,一旦operator从每个输入流收到检查点屏障。

对齐操作被跳过,operator持续处理所有的输入,甚至在检查点n的一些检查点屏障到达之后。这种情况下,operator在对检查点n进行状态快照之前也可能同时会处理属于检查点n+1的元素。因此,在恢复时,这些记录可能会导致重复,因为它们可能会既包含在针对检查点n的快照中,又将包含在检查点n之后被重放的部分数据中。

注意:对齐仅仅发生在operator有多个前置operator(join)以及operator有多个发送者(在一个流被repartitioning/shuffle之后)。正因为如此,令人尴尬的是,在数据流中仅仅只有一个并行的流操作(map(),flatMap(),filter()…)时,即便在至少一次的模式下也能提供恰巧一次的一致性保证。

恢复

在这个机制下的恢复是很简单的:如果产生了失败,Flink选择最近完成的检查点K。然后系统重放整个分布式的数据流,然后给予每个operator他们在检查点k快照中的状态。数据源被设置为从位置Sk开始重新读取流。例如在Apache Kafka中,那意味着告诉消费者从偏移量Sk开始重新消费。

如果状态被增量地快照,operator从最新的完整快照中读取状态然后在状态上应用一系列的增量快照更新。

本文翻译自:https://ci.apache.org/projects/flink/flink-docs-master/internals/stream_checkpointing.html


微信扫码关注公众号:Apache_Flink


QQ扫码关注QQ群:Apache Flink学习交流群(123414680)

时间: 2024-11-12 19:47:23

Apache Flink数据流的Fault Tolerance机制的相关文章

Apache Flink 数据流编程模型

抽象等级(Levels of Abstraction) Flink提供不同级别的抽象来开发流/批处理应用程序. Statefule Stream Processing: 是最低级别(底层)的抽象,只提供有状态的流.它通过ProcessFunction嵌入到DataStream API之中.它使得用户可以自由处理来源于一个或者多个流的事件 DataStream/DataSet API: 在我们的实际工作中,大多数的应用程序是不需要上文所描述的低级别(底层)抽象,而是相对于诸如DataStream

Apache Flink fault tolerance源码剖析(一)

因某些童鞋的建议,从这篇文章开始结合源码谈谈Flink Fault Tolerance相关的话题.上篇官方介绍的翻译是理解这个话题的前提,所以如果你想更深入得了解Flink Fault Tolerance的机制,推荐先读一下前篇文章理解它的实现原理.当然原理归原理,原理体现在代码实现里并不是想象中的那么直观.这里的源码剖析也是我学习以及理解的过程. 作为源码解析Flink Fault Tolerance的首篇文章,我们先暂且不谈太有深度的东西,先来了解一下:Flink哪里涉及到检查点/快照机制来

Apache Flink fault tolerance源码剖析(三)

上一篇文章我们探讨了基于定时任务的周期性检查点触发机制以及基于Akka的actor模型的消息驱动协同机制.这篇文章我们将探讨Zookeeper在Flink的Fault Tolerance所起到的作用. 其实,Flink引入Zookeeper的目的主要是让JobManager实现高可用(leader选举). 因为Zookeeper在Flink里存在多种应用场景,本篇我们还是将重心放在Fault Tolerance上,即讲解Zookeeper在检查点的恢复机制上发挥的作用. 如果用一幅图表示快照机制

Apache Flink fault tolerance源码剖析(二)

继续Flink Fault Tolerance机制剖析.上一篇文章我们结合代码讲解了Flink中检查点是如何应用的(如何根据快照做失败恢复,以及检查点被应用的场景),这篇我们来谈谈检查点的触发机制以及基于Actor的消息驱动的协同机制.这篇涉及到一个非常关键的类--CheckpointCoordinator. org.apache.flink.runtime.checkpoint.CheckpointCoordinator 该类可以理解为检查点的协调器,用来协调operator和state的分布

Apache Flink fault tolerance源码剖析(四)

上篇文章我们探讨了Zookeeper在Flink的fault tolerance中发挥的作用(存储/恢复已完成的检查点以及检查点编号生成器). 这篇文章会谈论一种特殊的检查点,Flink将之命名为--Savepoint(保存点). 因为保存点只不过是一种特殊的检查点,所以在Flink中并没有太多代码实现.但作为一个特性,值得花费一个篇幅来介绍. 检查点VS保存点 使用数据流API编写的程序可以从保存点来恢复执行.保存点允许你在更新程序的同时还能保证Flink集群不丢失任何状态. 保存点是人工触发

Apache Flink fault tolerance源码剖析完结篇

这篇文章是对Flinkfault tolerance的一个总结.虽然还有些细节没有涉及到,但是基本的实现要点在这个系列中都已提及. 回顾这个系列,每篇文章都至少涉及一个知识点.我们来挨个总结一下. 恢复机制实现 Flink中通常需要进行状态恢复的对象是operator以及function.它们通过不同的方式来达到状态快照以及状态恢复的能力.其中function通过实现Checkpointed的接口,而operator通过实现StreamOpeator接口.这两个接口的行为是类似的. 当然对于数据

Apache Flink fault tolerance源码剖析(五)

上一篇文章我们谈论了保存点的相关内容,其中就谈到了保存点状态的存储.这篇文章我们来探讨用户程序状态的存储,也是在之前的文章中多次提及的state backend(中文暂译为状态终端). 基于数据流API而编写的程序经常以各种各样的形式保存着状态: 窗口收集/聚合元素(这里的元素可以看作是窗口的状态)直到它们被触发 转换函数可能会使用key/value状态接口来存储数据 转换函数可能实现Checkpointed接口来让它们的本地变量受益于fault tolerant机制 当检查点机制工作时,上面谈

Flink Program Guide (9) -- StateBackend : Fault Tolerance(Basic API Concepts -- For Java)

State Backends 本文翻译自文档Streaming Guide / Fault Tolerance / StateBackend ----------------------------------------------------------------------------------------- 使用Data Stream API编写的程序通常以多种形式维护状态: ·  窗口将收集element或在它被触发后聚合element ·  Transformation方法可能会

Flink Program Guide (7) -- 容错 Fault Tolerance(DataStream API编程指导 -- For Java)

false false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt