Flink程序的执行具有并行、分布式的特性。
在执行过程中,一个流(stream)包含一个或多个分区(stream partition),而每一个算子(operator)可以包含一个或多个子任务(operator subtask),这些子任务在不同的线程、不同的物理机或不同的容器中彼此互不依赖地执行。
一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)。一般情况下,一个流程序的并行度,可以认为就是其所有算子中最大的并行度。一个程序中,不同的算子可能具有不同的并行度。
streamEnv.setParallelism(1)//加在ENV上表示默认所有的算子平行度都是1
Stream在算子之间传输数据的形式可以是one-to-one(forwarding)的模式也可以是redistributing的模式,具体是哪一种形式,取决于算子的种类。
One-to-one:stream(比如在source和map operator之间)维护着分区以及元素的顺序。那意味着map 算子的子任务看到的元素的个数以及顺序跟source 算子的子任务生产的元素的个数、顺序相同,map、fliter、flatMap等算子都是one-to-one的对应关系。
类似于spark中的窄依赖
Redistributing:stream(map()跟keyBy/window之间或者keyBy/window跟sink之间)的分区会发生改变。每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务。例如,keyBy() 基于hashCode重分区、broadcast和rebalance会随机重新分区,这些算子都会引起redistribute(重新分配过程)过程,而redistribute过程就类似于Spark中的shuffle过程。
类似于spark中的宽依赖
博主解析:
并行度就是在执行过程中,尤其是我们Flink的Job执行过程中,一个流(Stream)包含一个或者多个分区.由于他包含一个或多个分区,从而就造成了一个算子他就包含一个或者多个子任务.实际上这流(Stream)和算子,这两个是因果关系.就因为你这流包含了一个或者两个或者多个分区.从而造成流所对应的算子就会出现一个或者多个子任务.这些子任务在不同的Slot上运行.而且也可能是不同的物理机.或者是不同的不同的容器,彼此之间相互互不依赖地执行.但是实际上他们有依赖关系吗?实际上他们也有依赖关系的.完全没有依赖关系是不可能的,因为我们还有一个数据的依赖.因为我们的数据一定是从上一个子任务到下一个子任务的.
一个特定的算子它到底有多少个子任务呢?就是由我们这个并行度来决定的.而并行度就是由我们parallelism来设置的.我们可以在代码的后面通过setParallelism()方法来设置并行度.也可以统一的在ENV,来设置算子的并行度.在ENV上设置算子的并行度就是所谓默认的.由于我们设置了并行度,所以就造成了两种情况.就是造成了我们的Stream和Stream之间有两种关系存在.
一种是One-to-one(一对一对应关系),还有一种就是Redistributing(重新分配)
One-to-one:就是一个对应一个.什么情况下才是一个对应一个呢?
如图所示:
Redistribute:重新分配的意思,实际上就是变了.本来可能是只有一个并行度,通过一个算子之后变成了两个或者三个等并行度了
如图所示:
目前Flink的dataStream支持8种物理分区策略
1 | ①GlobalPartitioner(全局分区): 数据会被分发到下游算子的第一个实例中进行处理。 |
Flink8种传输数据操作
1 | KeyBy: 按照key的hash值分区, 相同的key一定会分到相同的分区.即相同的key进入相同的并行度,也就是说进入同一个子任务. |
- 本文作者: xubatian
- 本文链接: http://xubatian.cn/Flink-原理与实现-Flink核心概念之并行度(Parallelism)/
- 版权声明: 本博客所有文章除特别声明外均为原创,采用 CC BY 4.0 CN协议 许可协议。转载请注明出处:https://www.xubatian.cn/