Spark是如何划分物理执行计划的

Spark是如何划分物理执行计划的

Spark具体采用3个步骤来生成物理执行计划:

1.首先根据action操作顺序将应用划分为作业(job)

2.然后根据每个job的逻辑处理流程中的ShuffleDependency依赖关系,将job划分为执行阶段(stage)

3.最后在每个stage中,根据最后生成的RDD的分区个数生成多个计算任务(task)

下面我们根据一个例子来详细解释上述步骤。

在这里插入图片描述

如上图所示,这是一个Spark程序的逻辑执行流程。根据物理执行计划的划分步骤1,我们可以划分出一个作业(job)。因为整个逻辑处理流程只有图上的Results执行了action操作。由此可得下图:

在这里插入图片描述

根据物理执行计划的划分步骤2,我们可以划分出三个stage,如下图所示:

在这里插入图片描述

上图中,省略了第一步Job的划分,主要是为了读者能看清Stage的划分。Stage按照ShuffleDependency进行划分。如果读者不知道什么是ShuffleDependency,请移步至我的另一篇文章《Spark中的宽依赖和窄依赖是什么》。

根据物理执行计划的划分步骤3,我们可以划分出每个Stage中的task。

在这里插入图片描述

上图中一条带箭头的黑色粗直线表示一个task(ps:一条直线穿过多个RDD)。细心的读者会发现,此处没有对shuffle过程划分task。原因是同一个stage内部只有窄依赖(NarrowDependency),也就是说数据计算过程中不需要进行shuffle操作,这样就可以使用“流水线”式计算来提高task的执行效率,减少内存使用量。这也是Spark可以在有限内存中处理大规模数据的原因。

还有最后一个问题值得讨论:为什么stage之间(就是上图中红色箭头部分)没有进行task划分,应该如何对stage之间的操作划分task。

对于上述问题,我们可以从图中看出,stage之间存在的依赖关系是ShuffleDependency,而ShuffleDependency是部分依赖的(如果读者不清楚什么是ShuffleDependency可以移步至《Spark中的宽依赖和窄依赖是什么》),也就是下游stage中的每个task需要从parent RDD的每个分区中获取部分数据。

ShuffleDependency的数据划分需要上游stage预先将输出数据进行划分,按照分区存放,分区个数与下游task的个数一致,这个过程被成为“Shuffle Write”。按照分区存放完成后,下游的Task将属于自己分区的数据通过网络传输获取,然后将来自上游不同分区的数据聚合在一起进行处理,这个过程被成为“Shuffle Read”。总的来说,不同Stage的Task之间通过Shuffle Write + Shuffle Read传递数据,不能单纯依靠划分Task完成所有操作。至于如何具体进行Shuffle操作,分区数据是写内存还是磁盘,如何对这些数据进行聚合,我会单独出一篇文章进行介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值