《Flink 技术内幕之Data Streaming 容错》(官网翻译)

目录

一、介绍

二、Checkpoint

三、Barriers

四、State

​ 五、精确一次和至少一次

六、异步状态快照

七、Recovery

八、Operator 快照实现


一、介绍

Apache Flink提供了一种容错机制,可以一致地恢复数据流应用程序的状态。该机制确保即使出现故障,程序的状态最终也将准确地反映数据流中的每条记录(exactly once)。请注意,有一个开关将保证降级到至少一次(如下所述)。

容错机制不断地绘制分布式流数据流的快照。对于状态较小的流应用程序,这些快照非常轻量级,可以频繁地绘制,而不会对性能造成太大影响。流应用程序的状态存储在一个可配置的位置(例如主节点或HDFS)。

如果程序失败(由于机器、网络或软件故障),Flink将停止分布式流数据流。然后系统重新启动operators,并将它们重置为最新的成功检查点。输入流被重置为状态快照的点。任何作为重新启动的并行数据流的记录都保证不属于以前检查点状态的一部分。

注意:默认情况下,检查点是禁用的。有关如何启用和配置检查点的详细信息,请参阅检查点。

注意:要使此机制实现其全部保证,数据源(如消息队列或代理)需要能够将流回滚到定义的最近点。Apache Kafka有这个功能,Flink到Kafka的connector 利用了这个功能。有关Flink连接器提供的保证的更多信息,请参阅数据源和接收器的容错保证

注意:因为Flink的检查点是通过分布式快照实现的,所以我们可以互换使用snapshot和检查点这两个词。

二、Checkpoint

Flink容错机制的核心部分是绘制分布式数据流和操作符状态的一致快照。这些快照充当一致的检查点,在出现故障时,系统可以退回到这些检查点。Flink绘制这些快照的机制在“Lightweight Asynchronous Snapshots for Distributed Dataflows”中进行了描述。它受到分布式快照的标准Chandy-Lamport算法的启发,并特别针对Flink的执行模型进行了调整。】

三、Barriers

Flink分布式快照的一个核心元素是stream barriers。这些barriers被注入到数据流中,并和记录一起成为数据流的一部分。barriers永远追不上记录,流严格按照规定进行。一个barrier将数据流中的记录分隔为进入当前快照的记录集和进入下一个快照的记录集。每个barrier都携带快照的ID,这个快照的记录都已被推到barrier(ID)的前面。barrier不会中断流,因此非常轻。来自不同快照的多个barrier可以同时出现在流中,这意味着各种快照可能同时发生。

Stream barriers被注入stream source的并行数据流。快照n的barrier被注入的位置(我们称之为Sn)是stream source中快照覆盖数据的位置。例如,在Apache Kafka中,这个位置将是分区中最后一条记录的offset。这个位置Sn报告给检查点协调器(Flink的作业管理器)。

这些barriers随后流向下游。当一个中间operator从其所有输入流接收到快照n的barrier时,它将快照n的barrier发送到其所有输出流。一旦一个sink operator(streaming  DAG的末尾)从其所有输入流接收到barrier n,它就向检查点协调器确认快照n。在所有sink operator都确认快照之后,就认为快照已经完成。

快照n完成后,作业将不再向source 请求来自Sn之前的记录,因为此时这些记录(及其后代记录)已经通过了整个数据流拓扑。

接收多个输入流的operators 需要在快照barriers上对齐输入流。上图说明了这一点: 

  • 一旦operator从输入流接收到快照barrier n,它就不能再处理来自该流的任何其他记录,直到它也从其他输入接收到barrier n。否则,它将混淆属于snapshot n的记录和属于snapshot n+1的记录。
  • 报告barrier n的流被暂时搁置。从这些流接收的记录不会被处理,而是被放入输入缓冲区。
  • 一旦最后一个流接收到barrier n,操作符将发出所有挂起的输出记录,然后自己发出snapshot n barrier。
  • 之后,它将继续处理来自所有输入流的记录,在处理来自流的记录之前处理来自输入缓冲区的记录。

四、State

当操作符包含任何形式的状态时,此状态也必须是快照的一部分。操作符状态有不同的形式:

  • 用户定义状态:这是由转换函数(如map()或filter())直接创建和修改的状态。有关详细信息,请参见流应用程序中的状态。
  • 系统状态:这个状态是指数据缓冲区(operator计算的一部分)。这种状态的一个典型例子是窗口缓冲区,系统在其中收集(和聚合)窗口记录,直到计算和清除窗口为止。

operator 在从其输入流接收到所有快照barriers时,在将barriers发送到其输出流之前,对其状态进行快照。此时,对barrier之前的记录的所有状态更新都已完成,并且在barrier之后不会对依赖于barrier之后的记录进行更新。因为快照的状态可能很大,所以它存储在一个可配置的state backend。默认情况下,是JobManager的内存,但是对于生产使用,应该配置分布式可靠存储(例如HDFS)。在状态存储之后,operator确认检查点,将快照屏障发送到输出流中,然后继续。

生成的快照现在包含:

五、精确一次和至少一次

 

  • 对于每个并行流数据源,快照启动时流中的偏移量/位置
  • 对于每个操作符,指向作为快照的一部分存储的状态的指针

对齐步骤可能会给流程序增加延迟。通常,这种额外的延迟约为几毫秒,但是我们已经看到一些异常的延迟明显增加的情况。对于所有记录都需要持续超低延迟(几毫秒)的应用程序,Flink有一个开关,可以在检查点期间跳过流对齐。当operator 从每个输入中看到检查点屏障时,检查点快照仍然被绘制出来。

当跳过对齐时,operator 将持续处理所有输入,即使在检查点n的某些检查点屏障到达之后也是如此。这样,在获取检查点n的状态快照之前,操作符还处理属于检查点n+1的元素。在恢复时,这些记录将以重复的形式出现,因为它们都包含在检查点n的状态快照中,并且将在检查点n之后作为数据的一部分重新播放。

注意:对齐只发生在具有多个前身(连接)的operator和具有多个发送者的operator(在流重新分区/洗牌之后)。因此,只有令人尴尬的并行流操作(map()、flatMap()、filter()、…)的数据流实际上只提供一次保证,即使在至少一次模式下也是如此。

六、异步状态快照

注意,上面描述的机制意味着operator在state backend 存储状态快照时停止处理输入记录。每次捕获快照时,此同步状态快照都会引入延迟。

可以让operator 在存储状态快照时继续处理,从而有效地让状态快照在后台异步发生。要做到这一点,operator必须能够生成一个状态对象,该对象应该以一种对operator状态的进一步修改不会影响该状态对象的方式存储。例如,在RocksDB中使用的即写即拷数据结构具有这种行为。

在接收到其输入上的检查点屏障之后,operator启动对其状态的异步快照复制。它立即向输出发出屏障,并继续进行常规的流处理。一旦后台复制过程完成,它向检查点协调器(JobManager)确认检查点。检查点现在只有在所有接收到屏障和所有有状态operator确认它们的完整备份(可能是在屏障到达接收点之后)之后才完成。

有关状态快照的详细信息,请参见state backend

七、Recovery

恢复在这种机制下非常简单:当失败时,Flink选择最新的完整检查点k。然后系统重新部署整个分布式数据流,并给出存储在检查点k中的每个opeartor的状态。source设置为从Sk的处读取流。例如在Apache Kafka,这意味着告诉消费者开始从 offset Sk处获取。

如果以增量方式快照状态,操作符将从最新完整快照的状态开始,然后对该状态应用一系列增量快照更新。

有关更多信息,请参见重启策略

八、Operator 快照实现

operator快照拍摄可分为两部分:同步部分和异步部分。

operator和state backend 以Java FutureTask 形式提供快照。该任务包含同步完成部分和异步挂起部分的状态。然后,异步部分由该检查点的后台线程执行。

完全同步检查点operator返回一个已经完成的FutureTask。如果需要执行异步操作,则在该FutureTask的run()方法中执行。

这些任务是可取消的,因此可以释放流和其他资源消耗句柄。

原文地址:https://ci.apache.org/projects/flink/flink-docs-release-1.7/internals/stream_checkpointing.html

注:转载请注明出处

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章