Apache Flink 算子链 Operator Chain

您所在的位置:网站首页 flink提交流程 Apache Flink 算子链 Operator Chain

Apache Flink 算子链 Operator Chain

2023-03-13 10:30| 来源: 网络整理| 查看: 265

目录

算子任务间的数据传输

合并算子链

        我们仔细观察 Web UI 上给出的图,上面的节点似乎跟代码中的算子又不是一一对应的。

object BoundedStreamWordCount { def main(args: Array[String]): Unit = { val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment val lineDataStream: DataStream[String] = env.readTextFile("input/words.txt") val wordAndOne: DataStream[(String, Int)] = lineDataStream.flatMap((_: String).split(" ")).map((word: String) => (word, 1)) val wordAndOneGroup: KeyedStream[(String, Int), String] = wordAndOne.keyBy((_: (String, Int))._1) val sum: DataStream[(String, Int)] = wordAndOneGroup.sum(1) sum.print() env.execute() }

        很明显,这里的一个节点,会把转换处理的很多个任务都连接在一起,合并成了一个“大任务”。我们先来考察一下算子任务之间数据传输的方式。一个数据流在算子之间传输数据的形式可以是一对一(one-to-one)的直40通 (forwarding)模式,也可以是打乱的重分区(redistributing)模式,具体是哪一种形式,取决于算子的种类。

算子任务间的数据传输

 

(1)一对一(One-to-one,forwarding)

        这种模式下,数据流维护着分区以及元素的顺序。比如图中的 Source 和 map()算子,Source算子读取数据之后,可以直接发送给 map()算子做处理,它们之间不需要重新分区,也不需要调整数据的顺序。这就意味着 map() 算子的子任务,看到的元素个数和顺序跟 Source 算子的子任务产生的完全一样,保证着“一对一”的关系。map()、filter()、flatMap()等算子都是这种one-to-one 的对应关系。

(2)重分区(Redistributing)

        在 这 种 模 式 下 , 数 据 流 的 分 区 会 发 生 改 变 。 如 图 中 的 map() 和 后 面 的keyBy()/window()/apply()算子之间(这里的 keyBy()是数据传输方法,后面的 window()、apply()方法共同构成了窗口算子),以及窗口算子和 Sink 算子之间,都是这样的关系。每一个算子的子任务,会根据数据传输的策略,把数据发送到不同的下游目标任务。例如,keyBy()是分组操作,本质上基于键(key)的哈希值(hashCode)进行了重分区;而当并行度改变时,比如从并行度为 2 的 window 算子,要传递到并行度为 1 的 Sink 算子,这时的数据传输方式是再平衡(rebalance),会把数据均匀地向下游子任务分发出去。这些传输方式都会引起重分区(redistribute)的过程,这一过程类似于 Spark 中的 shuffle。

合并算子链

         在 Flink 中,并行度相同的一对一(one to one)算子操作,可以直接链接在一起形成一个“大”的任务(task),这样原来的算子就成为真正任务里的一部分,每个 task会被一个线程执行。这样的技术被称为“算子链”(Operator Chain)。

 

Flink 默认会按照算子链的原则进行链接合并,如果我们想要禁止合并或者自行定义,也可以在代码中对算子做一些特定的设置:

// 禁用算子链 .map((_,1)).disableChaining() // 从当前算子开始新链 .map((_,1)).startNewChain()



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3