Flink1.8探索系列~概念~数据流编程模型

数据流编程模型(Dataflow Programming Model)

  • Levels of Abstraction
  • Programs and Dataflows
  • Parallel Dataflows
  • Windows
  • Time
  • Stateful Operations
  • Checkpoints for Fault Tolerance
  • Batch on Streaming
  • Next step

Levels of Abstraction

Flink提供不同层次抽象来开发流/批处理应用程序。

1.最底层抽象只提供有状态流功能.它通过Process Function来嵌到DataStream API中.它允许用户使用一致的容错状态来处理来自1个或多个流的相关事件。此外,为实现复杂的业务计算,它还允许用户注册事件时间和处理时间回调。

2.在实际应用中,大多数应用程序都不会直接使用上面描述的最底层抽象,它们大多都会使用诸如像DataStream API (有界/无界流)和DataSet API (有界数据集)这样的核心API来编程. 这些fluent API为常用数据处理提供了各种构建块,例如:各种形式的转换,连接,聚合,窗口,状态等构建块. 在这些API中处理的数据类型在对应的编程语言中描述为类。

低层Process Function与DataStream API集成在一起,因此只能对某些操作进行低层抽象。 DataSet API在有界数据的基础之上提供了额外的原语,例如:loops/iterations.

3.Table API是以表为中心的声明式DSL,可以是动态更改表(代表流时)。 Table API遵循(扩展)关系模型:表附加了一个模式(类似于关系数据库中的表),并提供了比较操作,例如select,project,join,group-by,aggregate等。Table API程序可以以声明形式定义要执行的逻辑操作。 尽管Table API可以通过各种类型的用户定义函数进行扩展,但它的表现力不如Core API,但使用起来更简洁(编写的代码更少)。 此外,Table API程序还会在执行之前应用优化规则来对程序进行优化.

可以在表和DataStream / DataSet之间无缝转换,允许程序混合Table API以及DataStream和DataSet API。

4.Flink提供的最高层抽象是SQL。 这种抽象在语义和表达方面类似于Table API,但是它会将程序表示为SQL查询表达式。 SQL抽象与Table API紧密交互,SQL查询可以在Table API中定义的表上执行。

Programs and Dataflows

Flink程序的基本构建块是流(streams)和转换器(transformations)。从本质上说,Flink DataSet API中使用的DataSets其实也是流-后面会详细介绍。从概念上讲,流(streams)是数据记录流(没有终点),而转换(transformation)是将1个或多个流作为输入,并产生一个或多个输出流作为结果.

在执行时,Flink程序会被映射为streaming dataflows(由转换算子组成). 每个dataflow都开始于1个或多个sources,结束于1个或多个sinks. dataflows类似于有向无环图(directed acyclic graphs(DAGs)). 尽管可通过iteration结构生成特殊形式的环,但为了简单起见,大多数情况下都不会涉及这方面的内容.

一般来说,程序中的转换与dataflow中的算子会存在一对一的映射关系.

但有时,1个转换可能包含多个转换算子.

有关Sources和sinks的介绍,请参考streaming connectors和batch connectors文档.

有关Transformations的介绍,请参考DataStream operators和DataSet transformations文档.

Parallel Dataflows

从本质上讲,Flink程序是并行和分布式的.在执行期间,流(stream)可以分割成1个或多个流分区(stream partitions),并且每个算子(operator)者可拆分成1个或多个算子子任务(operator subtasks). 算子子任务之间是独立的,每个都在不同线程中运行(这些线程可能位于不同机器或容器).

算子子任务的数量取决于特定算子的并发度(parallelism)决定.流的并发度取决于生成它的算子的并发度。 同一程序的不同算子可能具有不同的并发度。

两个算子之间的流可按一对一模式重分配模式来转换数据:

一对一流(one-to-one stream)

比如上张图中Source和map()算子之间的流,这种流会保留元素的分区和顺序.

也就是说,map()算子的subtask[1]看到的元素顺序与Source算子的subtask[1]生成元素的顺序相同.

重分配流(redistributing pattern)

比如上图中map()和keyBy/window,keyBy/windowSink之间的流。这种流会改变流的分区.

根据所选转换器,每个算子子任务都会将数据发给不同目标的子任务. 示例是keyBy() (按key重新分区),broadcast()rebalance()(随机分区). 在重新分配交换中,它只在每对发送和接收子任务之间保留元素顺序(例如, map()的subtask[1]和keyBy/window的subtask[2] ). 因此在这个示例中,它会保留每个key内的元素顺序,但同时并发度(parallelism)又为不同key的聚合结果到达sink的顺序带来了不确实性.

有关配置和控制并发度的详细说明,请参考parallel execution文档.

Windows

聚合事件(Aggregating events,例如:counts, sums)在流上的工作方式与批处理有所不同.

例如,不能对流中的所有元素进行count计算,因为流是无界的. 因此,流上的聚合(counts, sums等聚合操作)必须通过windows来限定,例如: “对最后5分钟的数据进行count聚合”,或“对最后100个元素执行sum聚合”.

Windows既可通过time来驱动(例如:每30秒),也可通过数据来驱动(例如:每100个元素).

Windows包含多种人们通常区分不同类型的windows,例如tumbling windows(翻滚窗口,无重叠),sliding windows(滑动窗口,有重叠)和session windows(会话窗口,存在不活动间隙)。

更多window示例,可查看该blog post. 有关window的详情可参考window文档.

Time

当在流应用程序中引用time时(例如定义windows),可以参考以下不同的时间概念:

  • Event Time 是创建事件的时间,通常用事件中的时间戳(timestamp)来描述,例如:由传感器或生产服务附加的时间戳. Flink通过timestamp分配器来访问事件时间戳.
  • Ingestion time是事件在source算子处进入Flink数据流的时间。
  • Processing Time是每个算子在执行时间操作时的本地时间。

有关如何处理时间的详情,请参考事件时间文档.

Stateful Operations

虽然dataflow中的大多数操作一次只查看一个事件(例如,事件解析器),但有些操作会记住多个事件之间的相关信息(例如window算子). 这些需要记住信息的操作又称为有状态操作(stateful operations).

有状态操作的状态(state)保存在一个内嵌的key/value存储中. 状态(state)会根据流(指的是有状态算子读取的流)来分区和分发. 因此,只有调用了keyBy()函数之后才能在键流(keyed stream,即:按key来划分流)上访问key/value状态(并且只能访问与当前键相关联的值)。对齐流的key和state可以确保所有状态更新操作都在本地执行,在无事务开销的情况下保证一致性.

有关更多信息,请参考state.

Checkpoints for Fault Tolerance

Flink通过stream replaycheckpointing的组合来实现容错. checkpoint 与每个输入流中的特定点以及每个算子中的对应状态相关. 通过恢复算子的状态以及重播检查点事件可恢复dataflow,同时还可保证一致性(exactly-once处理语义).

检查点间隔是在执行期间利用恢复时间(需要重播的事件数)来权衡容错开销的一种方法。

有关Flink如何管理检查点的详细信息请参考fault tolerance internals.

有关如何启用和配置检查点的详细信息,请参阅checkpointing API docs.

Batch on Streaming

在Flink中,批处理程序只是流程序的一种特例,区别是在批量程序中流是有界的(元素数量是有限的). 在内部,DataSet会被视为数据流.因此,除了下边的少数例外外,大多数情况下,上述概念既适用于批处理程序也适用于流程序:

  • DataSet API中的有状态操作使用简化的内存/核外数据结构,而不是键/值索引。
  • DataSet API引入了特殊的同步(超级步骤)迭代,这些迭代只能在有界流上进行.详情可参考iteration文档.

下一步

阅读完了数据流编程模型,可继续了解Flink 分布式运行时概念.

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();