肥宅钓鱼网
当前位置: 首页 钓鱼百科

flink入门基础教程(看这篇文档就够了)

时间:2023-06-29 作者: 小编 阅读量: 1 栏目名: 钓鱼百科

Dataflow程序通常被表示为有向图,图中的顶点称为算子,表示计算;而边表示数据依赖关系。算子是Dataflow程序的基本功能单元,它们从输入获取数据,并对其进行计算,然后产生数据并发往输出以供后续处理。事件通常会根据其时间或其他数据属性分配到不同桶中。在窗口边界通过后,所有事件会发送给计算函数进行处理。图2-3是基于时间的滚动窗口将事件汇集到桶中,每10分钟触发一次计算。

到目前为止,我们已经介绍了流式应用是如何突破传统批处理的一些局限,还了解了开源流式处理框架的发展历程以及Flink流式应用的架构,接下来我们将正式进入流式数据处理的世界。

一 Dataflow 编程概述

在正式介绍流式处理的基础概念之前,我们先了解一下Dataflow编程,并建立起完整的术语体系。

1.1 Dataflow图1.1.1 Dataflow逻辑图

顾名思义,Dataflow程序描述了数据如何在不同操作之间的流动。Dataflow程序通常被表示为有向图,图中的顶点称为算子,表示计算;而边表示数据依赖关系。算子是 Dataflow 程序的基本功能单元,它们从输入获取数据,并对其进行计算,然后产生数据并发往输出以供后续处理。没有输入端的算子称为source,没有输出端的算子称为Sink。

图 1-1 展示了一个从推文输入流中提取并统计主题标签的Dataflow程序。类似图 1-1 的Dataflow图被称作逻辑图,因为它们表达了高层视角下的计算逻辑。

图1-1 Dataflow逻辑图

1.1.2 Dataflow物理图

为了执行Dataflow程序, 需要将逻辑图转化为Dataflow的物理执行性图。图1-2 展示了图 1-1 中逻辑图所对应Dataflow物理图。在Dataflow逻辑图中,顶点代表算子;在Dataflow物理图中,顶点代表任务。“抽取主题标签”和“计数”算子都包含两个并行算子任务,每个任务负责计算一部分输入数据。

图1-2 Dataflow物理图

1.2 数据并行和任务并行

例如,可以将输入数据分组,让同一操作的多个任务并行执行在不同数据子集上,这种并行称为数据并行(data parallelism)。数据并行非常有用,因为它能够将计算负载分配到多个节点上从而允许处理大规模的数据。

还可以让不同算子的任务(基于相同或不同的数据)并行计算, 这种并行称为任务井行(task parallelism)。通过任务并行,可以更好地利用集群的计算资源。

1.3数据传递策略

数据传递策略定义了如何将数据分配给物理Dataflow图中的不同任务。图1-3 描述了一些常见的数据传递策略类型。

图1-3 数据传输类型

1.3.1 转发策略(forward strategy)

在发送端任务和接收端任务之间一对一地进行数据传输。

1.3.2广播策略(broadcast strategy)

把每条数据发往直接下游的所有算子。

1.3.3 基于键值策略(key-based strategy)

根据键值属性对数据进行分区,并保证键值相同的数据会交由同一任务处理。

1.3.4 随机策略(random strategy)

将数据均匀分配给所有任务,实现计算任务的负载均衡。

二 并行处理流式数据

数据流中的事件包括监控数据、传感器测量值、信用卡交易、气象站观测数据、信息流的交互数据,以及网络搜索等。 接下来,我们将介绍如何利用Dataflow的编程模式并行处理流式数据。

2.1 延迟和吞吐

对于离线数据处理,我们最关心的是总的执行时间。由于流式数据是无限的,所以在数据流的处理世界中时没有总的执行时间这个概念的。流式数据处理最看重的是,到来的数据要及时处理。因此,我们主要从延迟和吞吐这方面的来考察实时应用的性能。

2.1.1 延迟

所谓延迟就是指,从接收事件到输出结果的消耗时长。在流处理中,延迟是以时间片(例如毫秒)为单位测量的。 Flink 可以提供低至几毫秒的延迟,可以说在数据到达的那一刻就开始处理。

2.1.2 吞吐

吞吐是用来衡量系统处理能力(处理速率)的指标,它告诉我们系统每单位时间可以处理多少事件。通常情况下是延迟越低越好,吞吐越高越好。

如果系统吞吐已到极限,一味提高事件到达速率只会让延迟更糟糕。如果系统持续以力不能及的高速率接收数据,那么缓冲区可能会用尽,继而可能导致数据丢失。这种情形通常被称为背压(backpressure),我们在后面会介绍怎么处理这种情况。

2.1.3 延迟与吞吐小结

延迟和吞吐并非相互独立的指标。如果事件在数据处理管道中传输时间太久,我们将难以确保高吞吐;同样,如果系统性能不足,事件很容易堆积缓冲,必须等待一段时间才能处理。

降低延迟实际上可以提高吞吐。显然,系统执行操作越快,相同时间内执行的操作数目就会越多。事实上,这就是在流处理管道中利用井行实现的效果。通过并行处理多条数据流,可以在处理更多事件的同时降低延迟。

2.2 数据流的操作类型2.2.1 数据流的操作状态

流数据处理既可以是无状态(Stateless)的,也可以是有状态(Stateful)的。

2.2.1.1 无状态操作

无状态的操作不会维持内部状态,即处理事件时无需依赖己处理过的事件,也不保存历史数据。由于事件处理互不影响且与事件到来的时间无关,无状态的操作很容易并行化。此外,如果发生故障,无状态的算子可以很容易地重启,并从中断处继续工作。

2.2.1.2 有状态操作

有状态算子可能需要维护之前接收的事件信息。它们的状态会根据传入的事件更新,并用于未来事件的处理逻辑中。有状态的流处理应用在并行化和容错方面会更具挑战性,因为它们需要对状态进行高效划分,并且在出错时需进行可靠的故障恢复。

2.2.2数据接入和数据输出
  • 数据接入操作是从外部数据源获取原始数据。可以从 TCP 套接字 、文件、 Kafka主题或传感器数据接口中获取数据。
  • 数据输出操作是将数据输出到外部系统,写入的目标可以是文件、数据库、消息队列或监控接口等。
2.2.2.1 转换操作(TRANSFORMATION)

转换操作会逐个读取事件,并对其进行某种转换后产生一条新的输出流。 如图 2-1 所示, 转换逻辑可以使用内置的转换算子,也可以使用用户自定义函数。我们会在后面的章节中介绍不同算子的语义。

图 2-1 转换操作

2.2.2.2 滚动聚合(ROLLING AGGREGATIONS)

滚动聚合 (如求和、求最小值和求最大值 ) 会根据每个到来的事件持续更新结果。聚合操作都是有状态的,它们通过将新到来的事件合并到已有状态来生成更新后的聚合值。图2-2 展示了一个求最小值的滚动聚合,其算子会维护当前的最小值,并根据每个到来的事件去更新这个值。

图2-2 滚动求最小值

2.2.2.3 窗口操作(WINDOW OPERATIONS)

窗口操作会持续创建一些称为“桶”的有限事件集合,并允许我们基于这些有限集进行计算。事件通常会根据其时间或其他数据属性分配到不同桶中。窗口的行为是由一系列策略定义的,这些窗口策略决定了什么时间创建桶,事件如何分配到桶中以及桶内数据在什么时间参与计算。我们可以基于时间(例如最近 5 秒钟接收的事件)、数量 (例如最新 100 个事件)或其他数据属性来定义窗口策略。

  • 滚动窗口(Tumbling windows):将事件分配到长度固定且互不重叠的桶中 。在窗口边界通过后,所有事件会发送给计算函数进行处理。基于数量(Count-based)的滚动窗口定义了在触发计算前需要集齐多少条事件。 图2-6 是基于数量的滚动窗口将输入流按每 4 个元素一组分配到不同的桶中。 基于时间(Time-based)的滚动窗口定义了在桶中缓冲数据的时间间隔。 图2-3 是基于时间的滚动窗口将事件汇集到桶中,每 10 分钟触发一次计算。

图2-3 基于数量的滚动窗口

图2-4 基于时间的滚动窗口

  • 滑动窗口(Sliding windows)将事件分配到大小固定且允许相互重叠的桶中,这意味着每个事件可能会同时属于多个桶。我们通过指定长度和滑动间隔来定义滑动窗口。滑动间隔决定每隔多久生成一个新的桶。在图2-5 中,基于数量的滑动窗口的长度为 4 个事件,滑动间隔为 3 个事件。

图2-5 滑动窗口

  • 会话窗口(Session windows )在一些常见的真实场景中非常有用,这些场景既不适合用滚动窗口也不适合用滑动窗口。假设有一个应用要在线分析用户行为,在该应用中我们要把事件按照用户的同一活动或会话来源进行分组。例如,用户浏览一连串新闻文章的交互过程可以看作一个会话。由于会话长度并非预先定义好,而是和实际数据有关,所以无论是滚动还是滑动窗口都无法适用于该场景。而我们需要一个窗口操作,能将属于同一会话的事件分配到相同桶中。会话窗口根据会话间隔(SessionGap)将事件分为不同的会话,该间隔值定义了会话在关闭前的非活动时间长度。图2-6 展示了一个会话窗口。

图2-6 会话窗口

如果你在收集来自不同传感器的测量值,那么可能会想在应用窗口计算前按照传感器 ID 对数据流进行划分。并行窗口中,每个数据分区所应用的窗口策略都相互独立。图2-7 展示了一个按事件颜色划分、基于数量 2 的并行滚动窗口。

图2-7 并行窗口

窗口操作与流处理中两个核心概念密切相关:时间语义(time semantics)和状态管理(state management)。时间可能是流处理中最重要的一个方面。当然,如果你的系统无法在故障时保护状态,那一切都是空谈。考虑到流式应用可能需要整日、甚至长年累月 地运行,因此必须保证出错时其状态能进行可靠的恢复,并且即使系统发生故障系统也能提供准确的结果。

三时间语义

在使用Flink编写流式处理程序时,避免不了和时间(Time)、水位线(WaterMark)打交道,理解这些概念是我们开发分布式流式应用的基础。

3.1 流式处理场景下的时间语义

当处理一个持续到达且无穷无尽的流式数据时,时间无疑是应用中最核心的要素。比如,我们想每分钟计算一次流量,那么一分钟在流式应用中的含义到底是什么呢?

假设有某个应用程序会分析用户玩在线手游时产生的事件。小灰是开心消消乐忠实玩家,小灰同学在上班坐地铁的路上都会玩这个游戏,但是在某个路段没有信号,手机突然断网了,小灰继续玩游戏,此时游戏产生的数据会缓存在手机里面。在手机信号好时,缓存在手机里的数据会发送给服务端。思考再来考虑这个问题,大数据团队分析在分析每分钟在线玩游戏场景时,一分钟的含义是什么呢?要把游戏掉线的时间算在内吗?图3-1描述了这个问题。

图3-1 流式数据延迟到达

如果我们仅仅考虑现实中每分钟收到多少数据,那结果必然会受到网络传输速度的影响,而事实上每分钟收到的事件数是由数据本身的时间来定义的。在这个开心消消乐的例子中,我们接触到了三个时间概念:事件生成时间(Event Time)、事件处理时间(Processing Time)和事件接入时间(Ingestion Time),下面我们将分别介绍这3种时间的概念。

3.1.1 事件生成时间(Event Time)

事件生成时间是数据流中事件实际发生的时间,它以附加在数据流中事件生成的时间戳为依据。这些时间戳通常在事件数据进入流处理管道之前就已经有了。如图3-2所示,即便事件有延迟,事件生成时间窗口也能准确地将事件分配到窗口中,从而反映出真实发生的情况。也就是说,无论数据流的处理速度如何、事件到达Flink算子的顺序是否会乱,最终生成的结果都是一样的。

图3-2 事件生成时间

3.1.2 事件处理时间(Processing Time)

事件处理时间是当前流处理算子所在机器上的本地时钟时间。基于处理时间的窗口会包含那些恰好在一段时间内到达窗口算子的事件,这里的时间段是按照机器时间测量的。如图3-3所示,在小灰的例子中,处理时间窗口在他手机离线后会继续计时,因此不会把她离线那段时间的活动考虑在内。也就是说,因为数据到达窗口的速率不同,所以Flink窗口算子中使用处理时间会导致不确定的结果。

图3-3 事件处理时间

3.1.3 事件接入时间(Ingestion Time)

事件在进入Flink的时间,即将每一个事件在数据源算子的处理时间作为事件时间的时间戳,并自动生成水位线(WaterMark会在后面介绍)。 Ingestion Time是 Event Time 和 Processing Time 的混合体,它表示事件进入流处理引擎的时间。和事件生成时间相比,事件接入时间(Ingestion Time)的价值不大,因为它的性能和事件时间类似,但却无法提供确定的结果。

3.1.4 三种时间对比

我们总结一下三种时间的特点,如图3-4所示,

  • Event Time:事件创建的时间
  • Processing Time:执行操作算子的本地系统时间,与机器相关
  • Ingestion Time:数据进入Flink的时间

图3-4 三种时间语义的比对

不知道你会不会有这样一个疑问:既然事件时间已经能够解决所有的问题了,那为何还要用处理时间呢?其实处理时间有其特定的使用场景,处理时间由于不用考虑事件的延迟与乱序,所以其处理数据的延迟较低。因此如果一些应用比较重视处理速度而非准确性,那么就可以使用处理时间。

3.2 水位线(WaterMark)

除了记录本身的时间戳, Flink基于事件时间的应用还必须提供水位线(watermark)。水位线用于在事件时间应用中推断每个任务当前的事件时间。基于时间的算子会使用这个时间来触发计算,并推动进度前进。例如:基于时间窗口的任务会在其事件时间,超过窗口结束边界时,进行最终的窗口计算并发出结果。

水位线就是一种Long类型的时间戳,如图3-5所示,矩形表示一条记录,三角形表示这条记录的事件时间戳(真实发生时间),圆圈表示水位线。可以看到下面的数据是乱序的,比如当算子接收到为2的水位线时,就可以认为时间戳小于等于2的数据都已经到来了,此时可以触发计算。但是事件时间3、事件时间5所对应的记录都在水位线2以后到达。同理,接收到为5的水位线时,就可以认为时间戳小于或等于5的数据都已经到来了,此时可以触发计算。

图3-5 包含时间戳和水位线的数据流

3.2.1 水位线的两个基本特征
  1. 必须单调递增,这是为了确保任务中的事件时间时钟正确前进,不会倒退。
  2. 和记录的时间戳存在联系,一个时间戳为T的水位线表示,接下来所有记录的时间戳一定都大于T。
3.2.2 水位线的作用

水位线的第二个属性,可以用来处理数据流中时间戳乱序的记录,例如图2-15中的时间戳3、5所对应的记录,就是时间乱序的记录。当任务收到一个时间戳小于或等于前一个水位线的记录时,我们把这类数据称作迟到记录。

四 状态和一致性模型

状态在数据处理中无处不在,任何一个稍复杂的计算都要用到它。为了生成结果,函数会在一段时间或基于一定个数的事件来累积状态(例如求和)。以某个滚动聚合算子为例,假设它会输出至今为止所见到的全部事件之和。该算子以内部状态形式存储当前的累加值,并会在每次收到新事件时对其进行更新。

由于流式算子处理的都是无穷无尽的数据,所以必须小心避免内部状态无限增长。为了限制状态大小,算子通常都会只保留到目前为止所见事件的摘要或概览。这种摘要可能是一个数量值,一个累加值,一个对至今为止全部事件的抽样, 一个窗口缓冲或是一个保留了应用运行过程中某些有价值信息的自定义数据结构。

不难想象,支持有状态算子将面临很多实现上的挑战:

4.1 任务故障

在流式作业中,算子的状态十分重要,因此需要在故障时予以保护。如果状态在故障期间丢失,那恢复后的结果就会不正确。流式作业通常会运行较长时间 ,因此状态可能是经过数天甚至数月才收集得到。通过重新处理所有输入来重建故障期间丢失的状态,不仅代价高,而且还很耗时。

什么是任务故障?

对于输入流中的每个事件,任务都需要执行以下步骤:

  1. 接收事件并将它们存在本地缓冲区;
  2. 选择性地更新内部状态;
  3. 产生输出记录。

上述任何一个步骤都可能发生故障,而系统必须在故障情况下明确定义其行为。 如果故障发生在第一步,事件是否会丢失?如果在更新内部状态后发生故障,系统恢复后是否会重复更新?在上述情况下,结果是否确定?

在批处理场景下,上面提到的都算不上问题。由于批处理任务可以轻易“从头再来”所以不会有任何事件丢失,状态也可以完全从最初开始构建。然而在流式场景中,处理故障就没那么容易了。流处理系统通过不同的结果保障来定义故障时的行为。接下来,我们一起来看看流式处理引擎是怎么保证结果正确的。

4.2结果保障

我们说的“结果保障”,指的是流处理引擎内部状态的一致性。也就是说,我们关注故障恢复后应用代码能够看到的状态值。请注意,保证应用状态的一致性和保证输出的一致性并不是一回事儿。一旦数据从sink端写出,除非目标系统支持事务,否则结果的正确性将难以保证。

4.2.1 最多一次(AT-MOST-ONCE)

任务发生故障时最简单的措施就是既不恢复丢失的状态,也不重放丢失的事件。最多一次是一种最简单的情况,它保证每个事件最多被处理一次。换句话说,事件可以随意丢弃,没有任何机制来保证结果的正确性。

4.2.2 至少一次(AT-LEAST-ONCE)

对大多数现实应用而言,用户期望是不丢事件,这类保障称为至少一次。它意味着所有事件最终都会处理,虽然有些可能会处理多次。但如果要计算某个事件在输入流中出现的次数,至少一次保障可能就会返回错误的结果。

4.2.3精确一次(EXACTLY-ONCE)

精确一次是最严格,也是最难实现的一类保障,它表示不但没有事件丢失,而且每个事件对于内部状态的更新都只有一次。本质上,精确一次保障意味着应用总会提供正确的结果,就如同故障从未发生过一样。Flink采用了轻量级检查点机制来实现精确一次结果保障。

4.2.4端到端的精确一次(END-TO-END EXACTLY-ONCE)

到目前为止你看到的保障类型都仅限于流处理引擎自身的应用状态。在实际流处理应用中,除了流处理引擎也至少还要有一个数据来源组件和一个数据终点组件。端到端的保障指的是在整个数据处理管道上结果都是正确的。有时候你可以通过弱保障来实现强语义。一个常见情况就是某个任务执行一些诸如求最大值或最小值的幕等操作。该情况下,你可以用至少一次保障来实现精确一次的语义。

五 总结

这篇文章主要介绍了数据流处理相关的基础知识。我们介绍了Dataflow编程模型以及如何将一个流式应用表示为分布式Dataflow 图。学习了并行处理无限流的需求,了解了延迟和吞吐对于流式应用的重要性。学习了流式应用中时间的含义,并比较了事件时间和处理时间的概念。最后我们介绍了状态对流式应用的重要性,以及如何应对故障并确保结果正确。

到目前为止,我们考虑的流处理相关概念都还是独立于 Apache Flink 的。后面我将继续输出Flink的系列问题。

希望这篇文章能起到抛砖引玉的作用,如有描述不当或者错误之处,还请大家在评论区留言指正。

    推荐阅读
  • 如何调整班组员工心态(怎么调整班组员工心态)

    只有组织成员在思想意识上高度统一没有分歧,才能确保措施从上之下具体贯彻落实,保证项目内部个体力量与目标方向相同,避免“内耗”现象,大大提高生产效率。在任务执行过程中,遇到意外情况,让员工提出解决方案。布置任务时明确要求,管理者经常会向组织成员下达工作安排。明确的要求可以避免员工之间的责任推委,极大的淡化了可能出现的管理矛盾。从而进一步激发员工的工作热情。

  • 韭菜的食用方法和营养价值(要说韭菜最突出的营养价值)

    目前没有研究证实,韭菜有提高性功能的作用。不过,韭菜中含硫化合物、锌、维生素C等物质对身体有一定好处,但与性功能没有直接的联系。与韭菜的壮阳功效相比,以下几点可能更值得我们关注。韭菜中的膳食纤维可以降低胆固醇吸收,预防心血管疾病。

  • 飞机的发明者是谁(飞机的发明者是莱特兄弟)

    1903年12月17日,莱特兄弟首次试飞了完全受控、依靠自身动力、机身比空气重、持续滞空不落地的飞机,也就是世界上第一架飞机“飞行者一号”。莱特兄弟首创了让飞机能受控飞行的飞行控制系统,从而为飞机的实用化奠定了基础,此项技术至今仍被应用在所有的飞机上。莱特兄弟的伟大发明改变了人类的交通、经济、生产和日常生活,同时也改变了军事史。

  • 鸽子喂食正确方法(如何给鸽子正确喂食)

    一旦训练强度上去,鸽子比较疲惫,免疫力下降的时候就比较容易生病,这一点尤其要注意。食物残留一定会污染食物,并且导致鸽群挑食。需要非常重视赛鸽粮食的干洁问题,干燥也是很重要的,粮食不能霉变。尤其是紧张训练的情况下,有些鸽子体质出现了一些下降,适当补充营养物质对于鸽子的身体很有好处。要想鸽子飞,食物营养补充的同时也要注意避免肥胖。喂食主要方式可以不变,但是不同训练阶段的变化要适当调整食物供给。

  • 轮胎的生产日期怎么看(三角轮胎的生产日期怎么看)

    轮胎一般分为内外侧,外侧正面标有轮胎的品牌、规格和生产日期。前两个代表生产周期,后两个代表生产年份。本规范适用于大多数家用汽车。此外,如果轮胎磨损严重,胎面厚度接近磨损痕迹,或者有鼓包或胎面变形无法修复,应尽快更换轮胎。但如果疤痕过大或胎壁破损,应尽快更换轮胎。因此,在轮胎明显磨损后,如果对更换一个轮胎有任何疑问,最好同时更换四个轮胎。另外,前轮胎损坏时,建议伤口较大时直接更换。

  • 汽车养护行业以后的路应该怎么走 汽车养护跟汽车保养

    截至目前,各类维修场所除个人维修店外,大致可分为三类:一是找全球各地的维修店,以自己的品牌提供落地服务,如一汽备件。他们采用与全球单家、多家大型维修店合作的形式,品牌推广,提供原厂维修产品,一汽所有乘用车均可使用,通用油机也可用于过滤其他车齿轮油,加盟店以较低的采购价格使用原厂产品。二是自建平台型小合作店,如胡涂汽车维修,利用线上宣传引流,争取更多客户。平台会推出自己的优势产品,会被更多人认可。

  • 偌大的意思(词语偌大的意思是什么)

    偌大,汉语词汇,拼音是:ruòdà,释义是这么大,那么大,今天小编就来聊一聊关于偌大的意思?接下来我们就一起去研究一下吧!出处明施耐庵《水浒传》第十四回:偌大去处,终不成官司禁打鱼鲜。清吴敬梓《儒林外史》第五十四回:“你开著偌大的人参铺,那在乎这几十两银子。”

  • 玉米田苗后除草剂的合理使用 玉米田苗后除草剂的合理使用方法

    农民朋友们都知道玉米田苗后,对生长环境的要求比较高,杂草丛生会降低玉米产量。具我站调查今年农户大多使用玉米田苗后除草剂。综上所述,玉米田苗后,选择一款适合的除草剂十分重要,但是正确的使用除草剂尤为关键,种植户应该谨遵建议,尽量在下午4点后使用除草剂,采用滴灌的方式,会事半功倍。使用除草剂后,不要割草,以免造成污染或者对人身带来损害。

  • 人类月球探索(人类月球日科技会)

    时至今日,世界上已有六个发射月球探测器的国家。7月13日,江苏扬州,本年度最大的超级月亮现身在扬州万福大桥之上。传说,月中有宫殿,为嫦娥所居。最后,“辉夜姬”在中秋之夜迎来了月宫使者,奔月而去。花香袭人,属于扩散现象,是花的香味分子运动的结果。兰州“90后”绣娘刘瑶近日完成了一组“敦煌手姿”刺绣作品。3月24日下午,浙江西湖断桥上演了浪漫的求婚。

  • 焉得虎子的上一句(讲述焉得虎子的出处)

    焉得虎子的上一句是不入虎穴不入虎穴,焉得虎子:焉:怎么不进老虎窝,怎能捉到小老虎比喻不亲历险境就不能获得成功,我来为大家科普一下关于焉得虎子的上一句?以下内容希望对你有帮助!焉得虎子的上一句焉得虎子的上一句是不入虎穴。不入虎穴焉得虎子的故事:班超是东汉时期有名的大将军,他曾作为东汉王朝的使者在西域活动了三十年,帮助西域各族拜托匈奴的束缚和奴役,为东汉王朝开发西域立下了汗马功劳。