Flink 编程模型

抽象层次

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)迭代接口,该接口仅能用于有界数据流。


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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容