抽象层次

 
levels_of_abstraction
  • 最低级的抽象接口是状态化的数据流接口(stateful streaming)。这个接口是通过 ProcessFunction 集成到 DataStream API 中的。该接口允许用户自由的处理来自一个或多个流中的事件,并使用一致的容错状态。另外,用户也可以通过注册 event time 和 processing time 处理回调函数的方法来实现复杂的计算。

  • 大部分程序通常会使用以 DataStream API(有界/无界数据流)、DataSet API(有界数据集)为代表的 Core APIs,并不会使用低级抽象接口。这些API为数据处理提供了大量的通用模块(common building block),包括用户定义的各种各样的变换(transformations)、连接(joins)、聚合(aggregations)、窗口(windows)、状态(state)等等。DataStream API 集成了 low level 处理函数,使得对一些特定的操作提供更低层次的抽象。此外,DataSet API 也为有界数据集提供了一些补充的编程原语,例如循环(loops)、迭代(iterations)等。

  • Table API 是一种以数据表为核心地声明式 DSL,能够动态地修改表(表示流时)。Table API 的是一种(扩展的)关系型模型:每个都有一个 schema(类似于关系型数据库中的表结构),API也提供以下操作: select,project,join,group by,aggregate等。Table API 程序定义的是应该执行什么样的逻辑操作,而不是直接准确地指定程序代码运行的具体步骤。尽管 Table API 可以通过各式各样的自定义函数进行扩展,但是它在表达能力上仍然比不上 Core APIs,不过在使用上更简练(可以减少很多代码)。此外,Table API 程序在运行之前也会使用一个优化器对程序进行优化。用户可以在 tables 与 DataStream/DataSet 之间进行无缝切换,程序也可以混合使用 Table API 和 DataStream/DataSet APIs。

  • Flink 提供的最高级接口是 SQL。这个层次的抽象接口和 Table API 非常相似,包括语法和接口的表现能力,唯一的区别是通过 SQL 查询语言实现程序。SQL 抽象接口和 Table API 的交互非常紧密,而且 SQL 查询也可以在 Table API 中定义的表上执行。

程序与数据流(Dataflow)

Flink 程序的基础构建单元是流(streams) 与转换(transformations)。DataSet API 中使用的数据集也是一种流。数据流(stream)就是一组永远不会停止的数据记录流,而转换(transformation)是将一个或多个流作为输入,并生成一个或多个输出流的操作。

执行时,Flink程序映射到 streaming dataflows,由流(streams)和转换操作(transformation operators)组成。每个 dataflow 从一个或多个源(source)开始,在一个或多个接收器(sink)中结束。dataflow 类似于有向无环图(DAG)。虽然可以通过迭代构造器生成某些特殊形式的环,但为了简化说明,大部分情况下我们不考虑这种结构。

通常情况下程序中的 transformation 和数据流图(dataflow)中的 operator 是一一对应的。不过有的时候也会出现一个 transformation 由多个operators 组成的情况。

 
Dataflow

并发数据流

Flink 程序是分布式、并发执行的。运行过程中,一个数据流可能会有一个或多个流分区(stream partitions),而一个 operator 也可能会有一个或多个运算子任务(operator subtasks)。运算子任务之间都是相互独立的,在不同的线程中运行的,可能在不同的机器或容器(container)上执行。运算子任务的数量由指定运算符(operator)的并发数确定。数据流的并发数就是它所生成的运算符的并发数。同一程序中不同的运算符可以有不同等级的并发量。

 
parallel_dataflow

数据流可以使用一对一的模式(one-to-one pattern)在两个运算符之间传输,也可以使用重分发模式(redistributing pattern):

  • 一对一模式,例如上图中 Source 和 map() 运算符之间的数据流。数据流中元素的分组和顺序会保持不变。也就是说,map() 运算符的子任务[1]所看见的元素与 Source 运算符的子任务[1]所生成的元素的顺序完全一致。

  • 重分发模式,例如上图中 map() 和 keyBy/window 运算符之间的数据流,以及 keyby/window 和 Sink 运算符之间的数据流。数据流所在的分区会改变。每个运算子任务会发送数据到不同的下游运算子任务(根据不同的运算转换)。例如 keyby() 运算符(通过对 key 进行哈希计算来重分区),boradcast() 和 rebalance()(随机重分区)就是重分发模式的例子。在此模式下,元素间的顺序只保留在每对发送-接收子任务中(例如 map() [1]和 keyBy/window[2])。尽管在子任务之间每个 key 的顺序都是确定的,但是由于程序的并发引入了不确定性,最终到达 Sink 的元素顺序就不能保证与一开始的元素顺序完全一致。

窗口

聚合事件(counts、sums 等)在流和批处理过程的工作模式完全不同。例如,计算数据流中的所有元素的个数是无法实现的,因为流在概念上是无限无边界的。因此,数据流的聚合操作都是由窗口(window)限定了范围来计算的,例如,“计算过去五分钟的元素个数”,“对最后100个元素求和”等。窗口可以时间驱动(例如以30秒为单位)或者数据驱动(例如以100个元素为单位)。有多种不同类型的窗口,例如,数据不重叠的滚动窗口(tumbling window)、数据重叠的滑动窗口(sliding window),以及以非活动状态为间隔的会话窗口(session window)。

 
window

时间

流式计算程序中的时间概念(例如在定义窗口时经常会用到的时间)有以下几种含义:

  • 事件时间(Event Time),是指事件发生的时间,通常在事件的内容中由时间戳表示。

  • 接入时间(Ingestion Time),是指事件在 source 运算符中进入 Flink 数据流的时间。

  • 处理时间(Processing Time),是指运算符在执行时间类操作时的本地时间。

 
time_model

有状态操作

虽然数据流中的许多操作一次只查看一个单独的事件,但有些操作会记录多个事件之间的信息(例如窗口运算符)。这种操作就称为有状态的操作(stateful)。
有状态操作的状态可以理解成是以键值对(key/value)形式存储。这个状态的分区和分布是和数据流严格绑定在一起的。因此,在 keyBy() 函数执行之后,只能在带键的数据流中访问 key/value 状态,而且也只能获取与当前事件的主键相对应的值。数据流的键和状态的严格对应,确保了所有状态更新都是本地操作,同时也保证了事务的一致性。这种方式也使得Flink可以透明地重分发状态,调整数据流分区。

 
stateful

容错检查点

Flink 通过流重放(stream replay)和检查点机制(checkpoint)结合的方式实现了容错能力。检查点与每个输入流中的特定一点以及每个操作的相应状态相关。数据流可以从检查点恢复来保持一致性(exactly-once的语义),通过恢复操作的状态和从检查点开始重放事件。检查点间隔是对程序的容错能力与恢复时间(需要重发的事件数量)的平衡手段。

批处理操作

Flink 将批处理看作一种特殊的流处理,只是数据流有界的特例。DataSet 也被看作一种流数据。流式计算程序中的很多概念也能应用到批处理程序中,除了以下几处不同:

  • 批处理程序的容错机制不使用检查点机制。而是通过完全重发所有数据流实现的,因为输入数据是有界的。这样,恢复过程中的开销可能更大一些,但是由于没有了检查点,正常处理过程的开销反而更小。

  • DataSet API 中的有状态操作没有使用键/值(key/value)索引存储,而是使用了简化的 in-memory/out-of-core 数据结构,

  • DataSet API 引入了特殊的同步(基于 superstep)迭代接口,该接口仅能用于有界数据流。


https://ci.apache.org/projects/flink/flink-docs-release-1.6/concepts/programming-model.html


 

转载:https://www.jianshu.com/p/79275f1a6057

Flink 编程模型的更多相关文章

  1. 第03讲:Flink 的编程模型与其他框架比较

    Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 本课时我们主要介绍 ...

  2. [Note] Apache Flink 的数据流编程模型

    Apache Flink 的数据流编程模型 抽象层次 Flink 为开发流式应用和批式应用设计了不同的抽象层次 状态化的流 抽象层次的最底层是状态化的流,它通过 ProcessFunction 嵌入到 ...

  3. flink原理介绍-数据流编程模型v1.4

    数据流编程模型 抽象级别 程序和数据流 并行数据流 窗口 时间 有状态操作 检查点(checkpoint)容错 批量流处理 下一步 抽象级别 flink针对 流式/批处理 应用提供了不同的抽象级别. ...

  4. Flink入门(四)——编程模型

    flink是一款开源的大数据流式处理框架,他可以同时批处理和流处理,具有容错性.高吞吐.低延迟等优势,本文简述flink的编程模型. 数据集类型: 无穷数据集:无穷的持续集成的数据集合 有界数据集:有 ...

  5. DataFlow编程模型与Spark Structured streaming

    流式(streaming)和批量( batch):流式数据,实际上更准确的说法应该是unbounded data(processing),也就是无边界的连续的数据的处理:对应的批量计算,更准确的说法是 ...

  6. JS魔法堂:深究JS异步编程模型

    前言  上周5在公司作了关于JS异步编程模型的技术分享,可能是内容太干的缘故吧,最后从大家的表情看出"这条粉肠到底在说啥?"的结果:(下面是PPT的讲义,具体的PPT和示例代码在h ...

  7. 多线程之异步编程: 经典和最新的异步编程模型,async与await

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  8. 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  9. jQuery插件编写及链式编程模型小结

    JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...

随机推荐

  1. 使用java读取excel数据

    package excelOperation2; import java.io.File; import java.io.FileNotFoundException; import java.util ...

  2. 力扣算法——136SingleNumber【E】

    Given a non-empty array of integers, every element appears twice except for one. Find that single on ...

  3. px2rem-loader(Vue:移动端自适应,px自动转化)

    1.下载lib-flexible npm i lib-flexible --save 2.引入lib-flexible import 'lib-flexible/flexible' 3.设置meta标 ...

  4. C# FTP操作代码实现

    C#  FTP 实现方式,废话不多说,直接上代码 public class FtpClient { #region 构造函数 /// <summary> /// 创建FTP工具 /// & ...

  5. 使用MySQL Workbench查询超时的错误

    MySQL Workbench是MySQL提供的连接工具,一直在用它.但是今天运行了一个SQL缺报出如下的错误: errcode 2013 lost connection to mysql serve ...

  6. windows xp .net framework 4.0 HttpWebRequest 报The underlying connection was closed,基础连接已关闭

    windows xp .net framework 4.0 HttpWebRequest 报The underlying connection was closed,基础连接已关闭,错误的解决方法 在 ...

  7. JNI中修改(基本类型)参数并返回到Java层使用

    最近在JNI相关项目中遇到一个问题:在Java层传入多个int类型的参数,在jni层修改参数值或地址之后重新返回到Java层.这应该算是基本知识了,尤其是基本类型的参数往往看似简单,所以在之前学习jn ...

  8. 2018-5-28-WPF-popup置顶

    title author date CreateTime categories WPF popup置顶 lindexi 2018-05-28 09:58:53 +0800 2018-2-13 17:2 ...

  9. list集合获取相同以及不同的对象

    List<StyleMenuModule> list1 = new ArrayList<>(); StyleMenuModule s1 = new StyleMenuModul ...

  10. leetcode-12双周赛-1245-树的直径

    题目描述: 方法一:深度优先: class Solution: def treeDiameter(self, edges: List[List[int]]) -> int: adjacency ...