写点什么

带你玩转 Flink 流批一体分布式实时处理引擎

  • 2022 年 1 月 17 日
  • 本文字数:10551 字

    阅读完需:约 35 分钟

摘要:Apache Flink 是为分布式、高性能的流处理应用程序打造的开源流处理框架。

 

本文分享自华为云社区《【云驻共创】手把手教你玩转Flink流批一体分布式实时处理引擎》,作者: 萌兔之约。

 

Apache Flink 是为分布式、高性能的流处理应用程序打造的开源流处理框架。Flink 不仅能提供同时支持高吞吐和 exactly-once 语义的实时计算,还能提供批量数据处理。相较于市面上的其他数据处理引擎,它采用的是基于流计算来模拟批处理。

一、Flink 原理及架构

Flink 简介

 

Apache Flink 是为分布式、高性能的流处理应用程序打造的开源流处理框架。Flink 不仅能提供同时支持高吞吐和 exactly-once 语义的实时计算,还能提供批量数据处理。主要由 Java 代码实现,支持实时流处理和批处理,批数据只是流数据的一个极限案例。支持了迭代计算,内存管理和程序优化。

 相较于市面上的其他数据处理引擎,Flink 和 Spark 都可以同时支持流处理和批处理。但是,Spark 的技术理念是基于批处理来模拟流的计算;而 Flink 则完全相反,它采用的是基于流计算来模拟批处理。

Flink 关键机制

 

 

四个机制:状态、时间、检查点、窗口

 

Flink 中有四种最重要的关键机制,这些关键机制在后面我们也会来进行详细的介绍,这里我们主要介绍它的基本概念以及主要用途。首先 Flink 中最重要的一个机制是状态机制(State),Flink 是一种有状态的流计算引擎。状态的作用主要是我们 Flink 是一种流计算,它需要存储节点的中间计算结果。另外状态的保存还有利于 Flink 进行容错恢复。状态有密切关系的是 Flink 的 Checkpoint,也就是检查点的机制,Checkpoint 能够去把 Flink 的状态进行存储,相当于是做一次快照,方便 Flink 进行容错恢复。另外因为 Flink 它是一种流计算引擎,它的数据是不间断产生的,是没有界限的,因此我们需要有一种机制能够对数据进行切分,我们会采用的时间(Time)作为切分点,另外 Flink 进行容错性的恢复,它也需要知道从哪个时间点来进行恢复。所以说时间也是 Flink 中一种很重要的机制。最后是窗口 window,在 Flink 中需要使用的窗口对数据进行切分,也方便对数据进行聚合计算。

Flink 核心理念

Flink 与其他流计算引擎的最大区别,就是状态管理。

 

Flink 提供了内置的状态管理,可以把工作时状态存储在 Flink 内部,而不需要把它存储在外部系统。这样做的好处:

  • 降低了计算引擎对外部系统的依赖,使得部署、运维更加简单;

  • 对性能带来了极大的提升。

Flink Runtime 整体架构

 

 

Flink 运行时架构从下至上可以分为了三层,在最下层是 Flink 的一些配置方式,Flink 可以采用单机的方式安装,也可以采用的集群的方式安装,另外也可以采用云的方式部署。在大多数情况下,Flink 都是采用的集群的方式进行配置和安装的。其中呢它支持了两种集群模式,一种是 Standalon,这种方式是采用了 Flink 自身提供的资源调度管理器。另外一种方式是基于 YARN 的方式进行了配置安装。

 

YARN 提供了专用的资源管理器。在中间层次是 Flink 的计算引擎,这个计算引擎它同时能够支持流处理和批处理,可以接收了上层的 api 提交给它做作业 。Runtime 这个引擎上面可以分为了两个模块,一个模块是 DataStream api,一个是 DataSet  api。Flink 向 dataset 和 datastream,也就是批数据集以及流数据集是分开处理的,但是都是公用下面的计算引擎。基于两种类型的 api,Flink 又提供了更多的上层的抽象的 api,API 越抽象,它的表达能力越弱,但是它对数据的处理能力、抽象性也越强。在针对于上层 Table api 和 SQL,它是主要是针对关系运算的,那针对关系数据的查询,Flink 提供了统一的接口,基于流数据 api,同时提供了复杂事件处理 api。复杂事件指的就是说对不能够用时间去表示事件的开始、次序以及结束这样的事件进行处理的 api 接口。另外针对于数据及 api,它提供了机器学习 api 以及图计算的 api。

Flink 核心概念- DataStream

 

 

DataStream: Flink 用类 DataStream 来表示程序中的流式数据。用户可以认为它们是含有重复数据的不可修改的集合(collection),DataStream 中元素的数量是无限的。

 

从图中我们可以发现,对 DataStream 可以使用一些算子,例如 KeyBy 这样的算子,对它进行处理转换之后,它会转换成另外一种数据流,也称为 keyedstream。那么基于 keyedstream,我们进一步可以使用窗口算子,这主要是 Flink 程序设计中对数据流的一些处理方式。

Flink 核心概念- DataSet

DataSet : Flink 系统可对数据集进行转换(例如,过滤,映射,联接,分组),数据集可从读取文件或从本地集合创建。结果通过接收器( Sink)返回,接收器可以将数据写入(分布式)文件或标准输出(例如命令行终端)

Flink 程序

 

Flink 程序由 Source、Transformation 和 Sink 三部分组成,其中 Source 主要负责数据的读取,支持 HDFS、kafka 和文本等;Transformation 主要负责对数据的转换操作; Sink 负责最终数据的输出,支持 HDFS、kafka 和文本输出等。在各部分之间流转的数据称为流( stream ) 。

Flink 数据源

批处理:

Files:HDFS,Local file system,MapR file system;Text,CSV,Avro,Hadoop input formats

JDBC、HBase 和 Collections

 

流处理:

Files、Socket streams、Kafka、RabbitMQ、Flume、Collections、 Implement your own 和 SourceFunction.collecto

Flink 程序运行图

 

 

​Flink 是一种 master-Slave 架构,它在启动的时候就会产生了 JobManger 以及 TaskManager。事实上在 Flink 程序中还包含两个组件,这两个组件一个叫 resource manager,主要负责了资源的调度与管理,另外一个称为 Dispatcher。主要是用来进行 client,要把 JobManager 进行分发公布。我们来看一看具体的运行流程。

首先是用户提交 Flink 程序,这个 Flink 程序就会转换成逻辑数据流图。客户端接收到逻辑数据流图之后,然后连同 jar 包以及一些依赖包就会提交给了 JobManger,JobManger 接收到逻辑数据流图之后会转成物理数据流图,这个物理数据流图是真实的可执行的,能够具体的将任务放置在 TaskManager 上,在 TaskManager 中会将它所拥有的资源划分成一个一个的 TaskSlot。每个 TaskSlot 实际上就相当于是 jvm,它的一个具体的线程。每个 TaskSlot 占用了 TaskManager 的一部分资源,这里的资源主要是以内存进行划分的,TaskSlot 不对 cpu 的资源进行划分,因此没有对 cpu 的资源进行隔离。

Flink 作业运行流程(一)

 

用户首先提交 Flink 程序到 JobClient,经过 JobClient 的处理、解析、优化提交到 JobManager,最后由 TaskManager 运行 task。

 

在 Flink 中它通过了 JobClient 提交了任务,做过 JobClient 提交的任务进一步的进行优化、解析以及处理,提交给了 JobManager。JobManager 会将 jobClient 提交了逻辑数据流图转换成物理数据流图,然后将这些任务分配给 taskmanager。taskmanager 接受到任务之后就相应地进行处理,并且汇报了 task 的状态给 JobManager,JobManager 最后就把结果反馈给 jobClient。

 

JobClient 是 Flink 程序和 JobManager 交互的桥梁。主要负责接收程序、解析程序的执行计划、优化程序的执行计划,然后提交执行计划到 JobManager。在 Flink 中主要有三类 Operator。

Source Operator:数据源操作,比如文件、socket、Kafka 等。

Transformation Operator:数据转换操作,比如 map,flatMap,reduce 等算子。

Sink Operator:数据存储操作。比如数据存储到 HDFS、Mysql、Kafka 等等。

一个完整的 Flink 程序---java


Flink 的数据处理

Apache Flink 它同时支持批处理和流处理,也能用来做一些基于事件的应用。

 

首先 Flink 是一个纯流式的计算引擎,它的基本数据模型是数据流。流可以是无边界的无限流,即一般意义上的流处理。也可以是有边界的有限流,就是批处理。因此 Flink 用一套架构同时支持了流处理和批处理。

 

其次,Flink 的一个优势是支持有状态的计算。如果处理一个事件(或一条数据)的结果只跟事 6 件本身的内容有关,称为无状态处理;反之结果还和之前处理过的事件有关,称为有状态处理。

有界流与无界流

无界流:有定义流的开始,但没有定义流的结束。数据源会无休止地产生数据。无界流的数据必须持续处理,即数据被读取后需要立刻处理。不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。

 

 

有界流:有定义流的开始,也有定义流的结束。有界流可以在读取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理。

批处理示例

 

 

批处理是流处理的一种非常特殊的情况。在流处理中,我们为数据定义滑动窗口或滚动窗口,并且在每次窗口滑动或滚动时生成结果。批处理则不同,我们定义一个全局窗口,所有的记录都属于同一个窗口。举例来说,以下代码表示一个简单的 Flink 程序,它负责每小时对某网站的访问者计数,并按照地区分组。

 

如果知道输入数据是有限的,则可以通过以下代码实现批处理。

 

 

如果输入数据是有限的,那么下面代码与上面代码的运行结果相同。

 

 Flink 批处理模型

 

Flink 通过一个底层引擎同时支持流处理和批处理。

 

在流处理引擎之上,Flink 有以下机制:

检查点机制和状态机制:用于实现容错、有状态的处理;

水印机制:用于实现事件时钟;

窗口和触发器:用于限制计算范围,并定义呈现结果的时间。

 

在同一个流处理引擎之上,Flink 还存在另一套机制,用于实现高效的批处理。

  • 用于调度和恢复的回溯法:由 Microsoft Dryad 引入,现在几乎用于所有批处理器;

  • 用于散列和排序的特殊内存数据结构:可以在需要时,将一部分数据从内存溢出到硬盘上;

  • 优化器:尽可能地缩短生成结果的时间。

 

​流与批处理机制

两套机制分别对应各自的 API(DataStream API 和 DataSet API);在创建 Flink 作业时,并不能通过将两者混合在一起来同时 利用 Flink 的所有功能。

Flink 支持两种关系型的 API,Table APl 和 sQL。这两个 API 都是批处理和流处理统一的 APl,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型 API 会以相同的语义执行查询,并产生相同的结果。

  • Table API / SQL 正在以流批统一的方式成为分析型用例的主要 API。

  • DataStream API 是数据驱动应用程序和数据管道的主要 API。

二、Flink 的 Time 与 Window

时间背景

 

在流处理器编程中,对于时间的处理是非常关键的。比如计数的例子,事件流数据(例如服务器日志数据、网页点击数据和交易数据)不断产生,我们需要用 key 将事件分组,并且每隔一段时间就针对每一个 key 对应的事件计数。这就是我们熟知的“大数据”应用。

流处理中的时间分类

在数据流处理过程中,我们经常使用系统处理时间即: processing time 作为某个事件的时间,而实际上系统时间 processing time 是我们强加给事件的时间,由于网络延迟等原因并不能较好的反应事件之间发生的先后顺序。

 

在实际场景中,每个事件的时间可以分为三种:

  • event time,即事件发生时的时间;

  • ingestion time,即事件到达流处理系统的时间;

  • processing time,即事件被系统处理的时间。

三种时间示例

例如,一条日志进入 Flink 的时间为 2019-11-1210:00:00.123,到达 window 的系统时间为 2019-11-1210:00:01.234,日志的内容如下:

2019-11-0218:37:15.624 INFO Fail over to rm2

2019-11-0218:37:15.624 是 Event Time;

2019-11-1210:00:00.123 是 Ingestion Time;

2019-11-1210:00:01.234 是 Processing Time;

三种时间的区别

实际情况中事件真正发生的先后顺序与系统处理时间存在一定的差异,这些差异主要由网络延迟、处理时间的长短等造成。如图所示:

 

 

横坐标代表 Event time,纵坐标代表 processing time。理想情况下,eventtime 和 processing time 构成的坐标应该形成一条倾斜角为 45 度的线。但实际应用过程中,processing time 要落后与 eventtime,造成事件到来的先后顺序不一致。

Flink 支持的时间语义

 

​Processing Time 是指事件数据被 Operator 处理时所在机器的系统时间,它提供了最好的性能和最低的延迟。

Event Time 是指在数据产生时该设备上对应的时间,这个时间在进入 Flink 之前已经存在于数据记录中了。

Ingestion Time 指的是事件数据进入到 Flink 的时间。

Window 概述

流式计算是一种被设计用于处理无限数据集的数据处理引擎,而无限数据集是指一种不断增长的本质上无限的数据集,而 Window 是一种切割无限数据为有限块进行处理的手段。Window 是无限数据流处理的核心,它将一个无限的 stream 拆分成有限大小的"buckets"桶,我们可以在这些桶上做计算操作。

Window 类型

Window 根据应用类型可以分成两类:

  • CountWindow:数据驱动,按照指定的数据条数生成一个 Window,与时间无关。

  •  TimeWindow:时间驱动,按照时间生成 Window。

 

​Apache Flink 是一个天然支持无限流数据处理的分布式计算框架,在 Flink 中 Window 可以将无限流切分成有限流。Flink 中 Window 可以是 Time Window,也可以是 Count Window。

TimeWindow 分类

TimeWindow 可以根据窗口实现原理的不同分成三类:滚动窗口(Tumbling Window ) .滑动窗口( Sliding Window)和会话窗口( Session Window)。

滚动窗口

将数据依据固定的窗口长度对数据进行切片。特点:时间对齐,窗口长度固定,没有重叠。

适用场景:适合做 Bl 统计等(做每个时间段的聚合计算)。

举一个例子,假设要对传感器输出的数值求和。一分钟滚动窗口收集最近一分钟的数值,并在一分钟结束时输出总和,如下图所示。

 滑动窗口

滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成。特点∶时间对齐,窗口长度固定,有重叠。

适用场景:对最近一个时间段内的统计(求某接口最近 5min 的失败率来决定是否要报警)。

示例:一分钟滑动窗口计算最近一分钟的数值总和,但每半分钟滑动一次并输出结果,如下图所示。

 

会话窗口

会话窗口由一系列事件组合一个指定时间长度的 timeout 间隙组成,类似于 web 应用的 session,也就是一段时间没有接收到新数据就会生成新的窗口。特点:时间无对齐。

 

代码定义

在 Flink 中,一分钟滚动窗口的定义如下:

stream.timeWindow(Time.minutes(1));

在 Flink 中,每半分钟(即 30 秒)滑动一次的一分钟滑动窗口,如下所示:

stream.timeWindow(Time.minutes(1),Time.seconds(30));

三、Flink 的 Watermark

乱序问题

 

流处理从事件产生,到流经 source,再到 operator,中间是有一个过程和时间的,虽然大部分情况下,流到 operator 的数据都是按照事件产生的时间顺序来的,但是也不排除由于网络、分布式等原因,导致乱序的产生,所谓乱序,就是指 Flink 接收到的事件的先后顺序不是严格按照事件的 Event Time 顺序排列的。 


 

此时出现一个问题,一旦出现乱序,如果只根据 eventTime 决定 window 的运行,我们不能明确数据是否全部到位,但又不能无限期的等下去,此时必须要有个机制来保证一个特定的时间后,必须触发 window 去进行计算了,这个特别的机制,就是 Watermark。

乱序示例

例子:某 App 会记录用户的所有点击行为,并回传日志(在网络不好的情况下,先保存在本地,延后回传)。A 用户在 11:02 对 App 进行操作,B 用户在 11:03 对 App 进行操作,但是 A 用户的网络不太稳定,回传日志延迟了,导致我们在服务端先接受到 B 用户 11:03 的消息,然后再接受到 A 用户 11:02 的消息,消息乱序了。

水位线(Watermark)

 

对于无穷数据集,我们缺乏一种有效的方式来判断数据完整性,因此就有了 Watermark,它是建立在事件时间上的一个概念,用来刻画数据流的完整性。如果按照处理时间来衡量事件,一切都是有序的、完美的,自然而然也就不需要 Watermark 了。换句话说事件时间带来了乱序的问题,而 Watermark 就是用来解决乱序问题。所谓的乱序,其实就是有事件延迟了,对于延迟的元素,我们不可能无限期的等下去,必须要有一种机制来保证一个特定的时间后,必须触发 Window 进行计算。这个特别的机制,就是 Watermark,它告诉了算子延迟到达的消息不应该再被接收。

 

  • Watermark 是一种衡量 Event Time 进展的机制。

    Watermark 是用于处理乱序事件的,而正确的处理乱序事件,通常用 Watermark 机制结合 window 来实现。

  • 数据流中的 Watermark 用于表示 timestamp 小于 Watermark 的数据,都已经到达了,因此,window 的执行也是由 Watermark 触发的。

  • Watermark 可以理解成一个延迟触发机制,我们可以设置 Watermark 的延时时长 t,每次系统会校验已经到达的数据中最大的 maxEventTime,然后认定 eventTime 小于 maxEventTime - t 的所有数据都已经到达,如果有窗口的停止时间等于 maxEventTime – t,那么这个窗口被触发执行。

    watermark 用来让程序自己平衡延迟和结果正确性

Watermark 的原理

 

Flink 怎么保证基于 event-time 的窗口在销毁的时候,已经处理完了所有的数据呢?

 

 

这就是 watermark 的功能所在。watermark 会携带一个单调递增的时间戳 t,Watermark(t)表示所有时间戳不大于 t 的数据都已经到来了,未来小于等于 t 的数据不会再来,因此可以放心地触发和销毁窗口了。

 

 

当 Flink,接收到数据时,会按照一定的规则去生成 Watermark,这条 Watermark 就等于当前所有到达数据中的 maExertT me"-延 N 时长,也就定说,Watermark 是基于数据携带的时间戳生成的,一旦 Watermark 比当前未触发的窗口的停止时间要晚,那么就会触发相应窗口的执行。由于 eventtime 是由数据携带的,因此,如果运行过程中无法获取新的数据,那么没有被触发的窗口将永远都不被触发。

 

上图中,我们设置的允许最大延迟到达时间为 2s,所以时间戳为 7s 的事件对应的 Watermark 是 5s,时间戳为 12s 的事件的 Watermark 是 10s,如果我们的窗口是 1s-5s,窗口 2 是 6s~-10s,那么时间戳为 7s 的事件到达时的 Matermarker.恰好触发窗口 1,时间戳为 12s 的事件到达时的 Watermark 恰好触发窗口 2。

 

Watermark 就是触发前一窗口的“关窗时间”,一旦触发关门那么以当前时刻为准在窗口范围内的所有所有数据都会收入窗中。只要没有达到水位那么不管现实中的时间推进了多久都不会触发关窗。

延迟的数据

Watermark 能够应对乱序的数据,但是真实世界中没法得到一个完美的 Watermark 数值。要么没法获取到,要么耗费太大,因此实际工作中会近似 Watermark(t)之后,还有较小的概率接受到时间戳 t 之前的数据,在 Flink 中将这些数据定义为“late elements”,同样可以在 Window 中指定允许延迟的最大时间(默认为О),可以使用下面的代码进行设置:

延迟数据处理机制

延迟事件是乱序事件的特例,和一般乱序事件不同的是它们的乱序程度超出了水位线( Watermark)的预计,导致窗口在它们到达之前已经关闭。

 

延迟事件出现时窗口已经关闭并产出了计算结果,对于此种情况处理的方法有 3 种:

  • 重新激活已经关闭的窗口并重新计算以修正结果。

  • 将延迟事件收集起来另外处理。

  • 将延迟事件视为错误消息并丢弃。

 

Flink 默认的处理方式是第 3 种直接丢弃,其他两种方式分别使用 Side Output 和 AllowedLateness。

Side Output 机制

Side Output 机制可以将延迟事件单独放入一个数据流分支,这会作为 Window 计算结果的副产品,以便用户获取并对其进行特殊处理。

 

side Output 获取延迟数据:

设置 allowedLateness 之后,迟来的数据同样可以触发窗口,进行输出,利用 Flink 的 sideoutput 机制,可以获取到这些延迟的数据,使用方式如下:

Allowed Lateness 机制

Allowed Lateness 机制允许用户设置一个允许的最大延迟时长。Flink 会在窗口关闭后一直保存窗口的状态直至超过允许延迟时长,这期间的延迟事件不会被丢弃,而是默认会触发窗口重新计算。因为保存窗口状态需要额外内存,并且如果窗口计算使用了 ProcessWindowFunction APl 还可能使得每个延迟事件触发一次窗口的全量计算,代价比较大,所以允许延迟时长不宜设得太长,延迟事件也不宜过多。

四、Flink 的容错

Flink 容错机制

 

为了保证程序的容错恢复以及程序启动时其状态恢复,Flink 任务都会开启 Checkpoint 或者触发 Savepoint 进行状态保存。

  • Checkpoint 机制。这种机制保证了实时程序运行时,即使突然遇到异常也能够进行自我恢复。Checkpoint 对于用户层面,是透明的,用户会感觉不到 Checkpoint 过程的存在。

  • Savepoint 机制。是在某个时间点程序状态全局镜像,以后程序在进行升级,或者修改并发度等情况,还能从保存的状态位继续启动恢复。Savepoint 可以看做是 Checkpoint 在特定时期的一个状态快照。

Checkpoint

Flink 如何保证 exactly-once 呢?它使用一种被称为“检查点( Checkpoint )”的特性,在出现故障时将系统重置回正确状态。Flink 状态保存主要依靠 Checkpoint 机制,Checkpoint 会定时制作分布式快照,对程序中的状态进行备份。

Checkpoint 检查点机制

Flink 中基于异步轻量级的分布式快照技术提供了 Checkpoints 容错机制,分布式快照可以将同一时间点 Task/Operator 的状态数据全局统一快照处理。Flink 会在输入的数据集上间隔性地生成 checkpoint barrier,通过棚栏( barrier)将间隔时间段内的数据划分到相应的 checkpoint 中。当应用出现异常时,Operator 就能够从上一次快照中恢复所有算子之前的状态,从而保证数据的一致性。

 

对于状态占用空间比较小的应用,快照产生过程非常轻量,高频率创建且对 Flink 任务性能影响相对较小。Checkpoint 过程中状态数据一般被保存在一个可配置的环境中,通常是在 JobManager 节点或 HDFS 上。

Checkpoint 配置

 

默认情况下 Flink 不开启检查点,用户需要在程序中通过调用 enableCheckpointing(n)方法配置和开启检查点,其中 n 为检查点执行的时间间隔,单位为毫秒。

 

exactly-once 和 at-least-once 语义选择

exactly-once:保证端到端数据一致性,数据要求高,不允许出现数据丢失和数据重复,Flink 的性能也相对较弱;

at-least-once:时延和吞吐量要求非常高但对数据的一致性要求不高的场景。

Flink 默认使用 exactly-once 模式,可以通过 setCheckpointingMode()方法来设定语义模式。

env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE)

 

Checkpoint 超时时间

指定每次 Checkpoint 执行过程中的上限时间范围,一旦 Checkpoint 执行时间超过该阈值,Flink 将会中断 Checkpoint 过程,并按照超时处理。

该指标可以通过 setCheckpointTimeout 方法设定,默认 10 分钟。

env.getCheckpointConfig().setCheckpointingTimeout(60000)

 

检查点之间最小时间间隔

设定两个 Checkpoint 之间的最小时间间隔,防止出现状态数据过大而导致 Checkpoint 执行时间过长,从而导致 Checkpoint 积压过多,最终 Flink 应用密集地触发 Checkpoint 操作,会占用大量计算资源而影响到整个应用的性能。

env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500)

 

最大并行执行的检查点数量

设定能够同时执行的 Checkpoint 数量。在默认情况下只有一个检查点可以运行,根据用户指定的数量可以同时触发多个 Checkpoint,从而提升 Checkpoint 整体的效率。

env.getCheckpointConfig().setMaxConcurrentCheckpoints(500)

 

外部检查点

设定周期性的外部检查点,然后将状态数据持久化到外部系统中,使用这种方式不会在任务停止的过程中清理掉检查点数据,而是一直保存在外部系统介质中,也可以通过从外部检查点中对任务就行恢复。

env.getCheckpointConfig().enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)

作业如何恢复数据?

 

Flink 在 Cancel 时允许在外部介质保留 Checkpoint;另一方面,Flink 还有另外一个机制是 SavePoint.

Savepoints 是检查点的一种特殊实现,底层其实是使用 Checkpoints 的机制。Savepoints 是用户以手工命令的方式触发,并将结果持久化到指定的存储路径中,目的是帮助用户在升级和维护集群过程中保存系统中的状态数据,避免因为停机运维或者升级应用等正常终止应用的操作而导致系统无法恢复到原有的计算状态的情况,从而无法实现端到端的 Exactly-Once 语义保证。

Savepoint 与 Checkpoint

 

 

checkpoint 的侧重点是“容错”,即 Flink 作业意外失败并重启之后,能够直接从早先打下的 checkpoint 恢复运行,且不影响作业逻辑的准确性。而 savepoint 的侧重点是“维护”,即 Flink 作业需要在人工干预下手动重启、升级、迁移或 A/B 测试时,先将状态整体写入可靠存储,维护完毕之后再从 savepoint 恢复现场。

 

savepoint 是“通过 checkpoint 机制”创建的,所以 savepoint 本质上是特殊的 checkpoint。

 

checkpoint 面向 Flink Runtime 本身,由 Flink 的各个 TaskManager 定时触发快照并自动清理,一般不需要用户干预;savepoint 面向用户,完全根据用户的需要触发与清理。

 

  • 触发管理方式上,Checkpoint 是由 Flink 自动触发并管理;Savepoint 由用户手动触发并管理

  • 主要用途上,Checkpoint 在 Task 发生异常时快速恢复,例如网络抖动导致的超时异常;Savepoint 有计划的进行备份,例如修改代码,调整并发

  • 从特点上看,Checkpoint 轻量,自动从故障中恢复,在作业停止后默认清除;Savepoint 持久,以标准格式存储,允许代码或配置发生改变,手动触发从 Savepoint 的恢复。

 

状态的存储方式-MemoryStateBackend

构造方式:

MemoryStateBackend(int maxStateSize, boolean asynchronousSnapshots)

存储方式:

- State: TaskManager 内存;Checkpoint: JobManager 内存。

容量限制:

单个 state maxStateSize 默认 5M; maxStateSize<=akka.framesize ,默认 10 M。·总大小不超过 JobManager 的内存

推荐使用的场景:本地测试;几乎无状态的作业,比如 ETL。

状态的存储方式- FsStateBackend

构造方式:

FsStateBackend(URI checkpointDataUri ,boolean asynchronousSnapshots)

存储方式:

State: TaskManager 内存;

CHeckpoint:外部文件存储系统(本地或 HDFS)。

容量限制:

  • 单 TaskManager 上 state 总量不超过它的内存;

  • 总大小不超过配置的文件系统容量。

推荐使用的场景:常规使用状态的作业,例如分钟级别窗口聚合、Join;需要开启 HA 的作业;可以在生产场景使用。

状态的存储方式- RocksDBStateBackend

构造方式:

RocksDBStateBackend(URI checkpointDataUri ,boolean enableIncrementalCheckpointing)

存储方式:

State: TaskManager 上的 KV 数据库(实际使用内存+磁盘);

CHeckpoint:外部文件存储系统(本地或 HDFS)。

容量限制:

单 TaskManager 上 State 总量不超过它的内存+磁盘;

单 Key 最大 2G;

总大小不超过配置的文件系统容量。

推荐使用的场景:超大状态的作业,例如天级别窗口聚合;需要开启 HA 的作业;要求不高的作业;可以在生产场景使用。

总结

 

本章主要讲述了 Flink 的架构及技术原理,以及 Flink 程序的运行过程。重点在于 Flink 流处理与批处理的不同方式,从长远来看,DataStream API 应该通过有界数据流完全包含 DataSet APl。

 

点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 2
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
带你玩转Flink流批一体分布式实时处理引擎