Flink-数据流编程

数据流是一个可能无限的事件序列。

一.数据流图

Flink-数据流编程_第1张图片

数据流程序描述了数据如何在算子之间流动,节点表示算子, 边表示数据之间的依赖性。

算子是数据流图中的功能单元,一个算子用来接收输入的数据,并将它们加工计算生成数据输出用于进一步处理。一个数据流图至少包含一个数据源和一个数据接收器。

二、数据并行与任务并行

第一,我们可以对输入的数据进行分区,并在数据子集上并行执行具有相同的算子的任务执行,这种类型的并行性就叫做数据并行性。

第二,我们可以将不同算子在相同或不同的数据上执行。这种并行性称为任务并行性。

三、数据交换策略

Flink-数据流编程_第2张图片

数据交换策略定义了在物理执行流图中如何将数据分配给任务。

3.1 向前策略

将数据从一个任务发送到接收任务,。如果俩个任务位于同一台物理机上,可以避免网络通信。

3.2 广播通信

将所有数据发送到算子的所有的并行任务上面去。因为这种策略会复制数据和涉及网络通信,所以 代价相当昂贵。

3.3 键控的策略

通过Key值(键)对数据进行分区保证具有相同Key的数据将由同一任务处理。在图2-2中,输出 “Extract hashtags”算子使用键来分区(hashtag),以便count算子的任务可以正确计算每个#标 签的出现次数。

3.4 随机策略

统一将数据分配到算子的任务中去,以便均匀地将负载分配到不同的计算任务。

并行处理数据

数据流中的事件可以表示监控数据,传感器测量数据,信用卡交易数据,气象站观测数据,在线用 户交互数据,网络搜索数据等。

四、延迟和吞吐量

流处理程序不同与批处理程序。在评估性能时,要求也有所不同。对于批处理程序,我们通常关心 一个作业的总的执行时间,或我们的处理引擎读取输入所需的时间,执行计算,并回写结果。由于 流处理程序是连续运行的,输入可能是无界的,所以数据流处理中没有总执行时间的概念。 相反, 流处理程序必须尽可能快的提供输入数据的计算结果。我们使用延迟和吞吐量来表征流处理的性能 要求。

延迟:

延迟表示处理事件所需的时间。它是接收事件和看到在输出中处理此事件的效果之间的时间间 隔。

在数据流中,延迟是以时间为单位测量的,例如毫秒。

吞吐量:

吞吐量是衡量系统处理能力的指标,也就是处理速率。

吞吐量以每个时间单位系统所能处理的事件数量或操作数量来衡量。值得注意的是,事件处理 速率取决于事件到达的速率,低吞吐量并不一定表示性能不佳。

应该清楚延迟和吞吐量不是独立指标。如果事件需要在处理流水线中待上很长时间,我们不能轻易 确保高吞吐量。同样,如果系统容量很小,事件将被缓冲,而且必须等待才能得到处理。

五、数据流的操作

流处理引擎通常提供一组内置操作:摄取(ingest),转换(transform)和输出流(output)。

5.1 数据的状态

无状态:

操作可以是无状态的或有状态的。无状态操作不保持任何内部状态。

事件的处理不依赖于过去看到的任何事件,也没有保留历史。

无状态操作很容易并行化,因为事件可以彼此独立地处理,也独立于事件到达的顺序(和事件 到达顺序没有关系)。

失败时无状态操作可以是简单的重新启动并从中断处继续处理。

有状态:

有状态操作可能会维护之前收到的事件的信息。

此状态可以通过传入事件更新,也可以用于未来事件的处理逻辑。

有状态的流处理应用程序更难以并行化和以容错的方式来运行,因为状态需要有效的进行分区和在发生故障的情况下可靠地恢复。

5.2 数据的摄取

数据摄取和数据出口操作允许流处理程序与外部系统通信。 数据摄取是操作从外部源获取原始数据并将其转换为其他格式(ETL)。 实现数据提取逻辑的运算符被称为数据源。数据源可以从TCP Socket,文件,Kafka Topic或传感 器数据接口中提取数据。 数据出口是以适合消费的形式产出到外部系统。 执行数据出口的运算符称为数据接收器,包括文件,数据库,消息队列和监控接口。

5.3 数据的转换

转换算子是单遍处理算子,碰到一个事件处理一个事件。

这些操作在使用后会消费一个事件,然后对事件数据做一些转换,产生一个新的输出流。

转换逻辑可以集成在 操作符中或由UDF函数提供

5.4 数据的滚动聚合

滚动聚合是一种聚合,例如sum,minimum和maximum,为每个输入事件不断更新。

聚合操作是有状态的,并将当前状态与传入事件一起计算以产生更新的聚合值。

能够有效地将当前状态与事件相结合产生单个值,聚合函数必须是关联的和可交换的。否则,操作 符必须存储完整的流数据历史。 操作符保持当前的最小值和相应地为每个传入的事件来更新最小值。

六、窗口操作符

6.1 含义

转换和滚动聚合一次处理一个事件产生输出事件并可能更新状态。但是,有些操作必须收集并缓冲 数据以计算其结果。

例如,考虑不同流之间的连接或整体聚合这样的操作,例如中值函数。为了在无界流上高效运行这 些操作符,我们需要限制 这些操作维护的数据量。

6.2 意义

如果我们只对最近的数据感兴趣的话会怎样?考虑给司机提供实时交通信息的应用程序。这个程序 可以使他们避免拥挤的路线。在这种场景下,你想知道某个位置在最近几分钟内是否有事故发生。 另一方面,了解所有发生过的事故在这个应用场景下并没有什么卵用。更重要的是,通过将流历史 缩减为单一聚合值,我们将丢失这段时间内数据的变化。例如,我们可能想知道每5分钟有多少车 辆穿过某个路口。

6.3 策略

窗口操作不断从无限事件流中创建有限的事件集,好让我们执行有限集的计算。

通常会基于数据属性或基于时间的窗口来分配事件。

要正确定义窗口运算符语义,我们需要确定如何给窗口分配事件以及对窗口中的元素进行求值的频 率是什么样的。

窗口的行为由一组策略定义。

窗口策略决定何时创建新的窗口以及要分配的事件属于哪个窗口,以及何时对窗口中的元素进 行求值。

一旦触发条件得到满足,窗口的内容将会被发送到求值函数,求值函数会将计算逻辑应用于窗 口中的元素。

求值函数可以是sum或minimal或自定义的聚合函数。 求值策略可以根据时间或者数据属性计算。

6.3.1 滚动窗口

滑动窗口是将事件分配到固定大小的不重叠的窗口中。

当通过窗口末尾的时候,全部事件会被发送到求值函数进行处理。基于计数的滑动窗口定义了在出发求值之前需要收集多少事件。

Flink-数据流编程_第3张图片

基于时间的窗口函数,将事件收集到窗口,每十分钟触发一次。

Flink-数据流编程_第4张图片

 6.3.2 滑动窗口

滑动窗口将事件分配到固定大小的重叠的窗口中。

通过提供窗口的长度和滑动距离来定义滑动窗口。滑动距离定义了创建新窗口的间隔。

基于滑动计数的窗口,长度为四个事件,三个为滑动距离。

Flink-数据流编程_第5张图片

 6.3.3 会话窗口

会话窗口在常见的真实场景中很有用,一些场景既不能使用滚动窗口也不能使用滑动窗口。

考虑一个分析在线用户行为的应用程序。在应用程序里,我们想把源自同一时期的用户活动或会话 事件分组在一起。 会话由一系列相邻时间发生的事件组成,接下来有一段时间没有活动。 例如,用户在App上浏览一系列的新闻,然后关掉App,那么浏览新闻这段时间的浏览事件就是一个会话。 会话窗口事先没有定义窗口的长度,而是取决于数据的实际情况,滚动窗口和滑动窗口无法应用于 这个场景。相反,我们需要将同一会话中的事件分配到同一个窗口中去,而不同的会话可能窗口长 度不一样。 会话窗口会定义一个间隙值来区分不同的会话。间隙值的意思是:用户一段时间内不活动,就认为 用户的会话结束了。 基于会话的窗口。Flink-数据流编程_第6张图片

 6.4 语义

在流处理中,窗口操作与两个主要概念密切相关:时间语义和状态管理。 时间也许是流处理最重要的方面。即使低延迟是流处理的一个有吸引力的特性,它的真正价值不仅 仅是快速分析。 真实世界的系统,网络和通信渠道远非完美,流数据经常被推迟或无序(乱序)到达。 理解如何在这种条件下提供准确和确定的结果是至关重要的。 更重要的是,流处理程序可以按原样 处理事件制作的也应该能够处理相同的历史事件方式,从而实现离线分析甚至时间旅行分析。 当 然,前提是我们的系统可以保存状态,因为可能有故障发生。到目前为止,我们看到的所有窗口类 型在产生结果前都需要保存之前的数据。实际上,如果我们想计算任何指标,即使是简单的计数, 我们也需要保存状态。考虑到流处理程序可能会运行几天,几个月甚至几年,我们需要确保状态可 以在发生故障的情况下可靠地恢复。 并且即使程序崩溃,我们的系统也能保证计算出准确的结果。 本章,我们将在流处理应用可能发生故障的语境下,深入探讨时间和状态的概念。

七、时间语义

7.1 时间就是金钱

7.2 处理时间

处理时间是处理流的应用程序的机器的本地时钟的时间(墙上时钟)。 处理时间的窗口包含了一个时间段内来到机器的所有事件。这个时间段指的是机器的墙上时钟。如 下图所示,在Alice的这个例子中,处理时间窗口在Alice的手机离线的情况下,时间将会继续行 走。但这个处理时间窗口将不会收集Alice的手机离线时产生的事件。Flink-数据流编程_第7张图片

 7.3 事件时间

事件时间是流中的事件实际发生的时间。事件时间基于流中的事件所包含的时间戳。通常情况下, 在事件进入流处理程序前,事件数据就已经包含了时间戳。下图展示了事件时间窗口将会正确的将 事件分发到窗口中去。可以如实反应事情是怎么发生的。即使事件可能存在延迟。 事件时间使得计算结果的过程不需要依赖处理数据的速度。基于事件时间的操作是可以预测的,而 计算结果也是确定的。无论流处理程序处理流数据的速度快或是慢,无论事件到达流处理程序的速 度快或是慢,事件时间窗口的计算结果都是一样的。 可以处理迟到的事件只是我们使用事件时间所克服的一个挑战而已。普遍存在的事件乱序问题可以 使用事件时间得到解决。考虑和Alice玩同样游戏的Bob,他恰好和Alice在同一趟地铁上。Alice和 Bob虽然玩的游戏一样,但他们的手机信号是不同的运营商提供的。当Alice的手机没信号时,Bob 的手机依然有信号,游戏数据可以正常发送出去。 如果使用事件时间,即使碰到了事件乱序到达的情况,我们也可以保证结果的正确性。还有,当我 们在处理可以重播的流数据时,由于时间戳的确定性,我们可以快进过去。也就是说,我们可以重 播一条流,然后分析历史数据,就好像流中的事件是实时发生一样。另外,我们可以快进历史数据来使我们的应用程序追上现在的事件,然后应用程序仍然是一个实时处理程序,而且业务逻辑不需 要改变。Flink-数据流编程_第8张图片

 7.4 水位线

在我们对事件时间窗口的讨论中,我们忽略了一个很重要的方面:我们应该怎样去决定何时触发事 件时间窗口的计算?也就是说,在我们可以确定一个时间点之前的所有事件都已经到达之前,我们 需要等待多久?我们如何知道事件是迟到的? 在分布式系统无法准确预测行为的现实条件下,以及外部组件所引发的事件的延迟,以上问题并没 有准确的答案。在本小节中,我们将会看到如何使用水位线来设置事件时间窗口的行为。 水位线是全局进度的度量标准。系统可以确信在一个时间点之后,不会有早于这个时间点发生的事 件到来了。本质上,水位线提供了一个逻辑时钟,这个逻辑时钟告诉系统当前的事件时间。当一个 运算符接收到含有时间T的水位线时,这个运算符会认为早于时间T的发生的事件已经全部都到达 了。 对于事件时间窗口和乱序事件的处理,水位线非常重要。运算符一旦接收到水位线,运算符会认为 一段时间内发生的所有事件都已经观察到,可以触发针对这段时间内所有事件的计算了。 水位线提供了一种结果可信度和延时之间的妥协。 激进的水位线设置可以保证低延迟,但结果的准确性不够。在这种情况下,迟到的事件有可能 晚于水位线到达,我们需要编写一些代码来处理迟到事件。 如果水位线设置的过于宽松,计算的结果准确性会很高,但可能会增加流处理程序不必要的延 时。 在很多真实世界的场景里面,系统无法获得足够的知识来完美的确定水位线。在手游这个场景中, 我们无法得知一个用户离线时间会有多长,他们可能正在穿越一条隧道,可能正在乘飞机,可能永 远不会再玩儿了。水位线无论是用户自定义的或者是自动生成的,在一个分布式系统中追踪全局的 时间进度都不是很容易。所以仅仅依靠水位线可能并不是一个很好的主意。流处理系统还需要提供 一些机制来处理迟到的元素(在水位线之后到达的事件)。根据应用场景,我们可能需要把迟到事 件丢弃掉,或者写到日志里,或者使用迟到事件来更新之前已经计算好的结果。

7.5 写在最后

既然事件时间已经可以解决我们的所有问题,为什么我们还要对比这两个时间概念? 真相是,处理时间在很多情况下依然很有用。处理时间窗口将会带来理论上最低的延迟。 因为我们不需要考虑迟到事件以及乱序事件,所以一个窗口只需要简单的缓存窗口内的数据即可, 一旦机器时间超过指定的处理时间窗口的结束时间,就会触发窗口的计算。 对于一些处理速度比结果准确性更重要的流处理程序,处理时间就派上用场了。另一个应用场景 是,当我们需要在真实的时间场景下,周期性的报告结果时,同时不考虑结果的准确性。 一个实时监控的仪表盘,负责显示当事件到达时立即聚合的结果。最后,处理时间窗口可以提 供流本身数据的忠实表达,对于一些案例可能是很必要的特性。 例如我们可能对观察流和对每分钟事件的计数(检测可能存在的停电状况)很感兴趣。简单的 说,处理时间提供了低延迟,同时结果也取决于处理速度,并且也不能保证确定性。另一方 面,事件时间保证了结果的确定性,同时还可以使我们能够处理迟到的或者乱序的事件流。

八、Flink的四大基石

8.1 Checkpoint

Flink 基于 Chandy-Lamport 算法实现了一个分布式的一致性的快照,从而提供了一致性的语义。
Chandy-Lamport 算法实际上在 1985 年的时候已经被提出来,但并没有被很广泛的应用,而 Flink 则把这
个算法发扬光大了。
Spark 最近在实现 Continue streaming Continue streaming 的目的是为了降低处理的延时,其也需要
提供这种一致性的语义,最终也采用了 Chandy-Lamport 这个算法,说明 Chandy-Lamport 算法在业界
得到了一定的肯定。
8.2 State
提供了一致性的语义之后, Flink 为了让用户在编程时能够更轻松、更容易地去管理状态,还提供了一套
非常简单明了的 State API ,包括 ValueState ListState MapState BroadcastState
8.3  Time
除此之外, Flink 还实现了 Watermark 的机制,能够支持基于事件的时间的处理,能够容忍迟到 / 乱序的数据。
8.4 Window
另外流计算中一般在对流数据进行操作之前都会先进行开窗,即基于一个什么样的窗口上做这个计算。
Flink 提供了开箱即用的各种窗口,比如滑动窗口、滚动窗口、会话窗口以及非常灵活的自定义的窗口。

你可能感兴趣的:(flink,大数据,big,data)