您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
shuffle什么意思(sx是什么意思)
算子,节点,数据shuffle什么意思(sx是什么意思)
发布时间:2019-02-08加入收藏来源:互联网点击:
DAGScheduler 创建最后一个 Stage:stage2
到此为止,我们的向导大人几乎跑断了腿、以首尾倒置的顺序对整片地形进行了地毯式搜查,最终将地形划分为 3 块战略区域(Stage)。那么问题来了,向导大人划分出的 3 块区域,有啥用呢?DAGScheduler 他老人家马不停蹄地这么跑,到底图啥?前面我们提到,DAGScheduler 的核心职责,是将抽象的 DAG 计算图转换为具体的、可并行计算的分布式任务。回溯 DAG、创建 Stage,只是这个核心职责的第一步,DAGScheduler 以 Stage(TaskSet)为粒度进行任务调度,伙同 TaskScheduler、SchedulerBackend 等一众大佬运筹帷幄、调兵遣将。不过,毕竟本篇的主题是 DAG,到 Spark 调度系统的核心还有些距离,因此这里咱们暂且挖个坑,后面再单独开篇(Spark 调度系统)专门讲述几位大佬之间的趣事逸闻。填坑之路漫漫其修远兮,吾将上下而挖坑。
咱们来回顾一下向导大人的心路历程,首先,DAGScheduler 沿着 DAG 的尾节点一路北上,并沿途判断每一个 RDD 节点的 dependencies 属性。之后,如果判定 RDD 的 dependencies 属性是 NarrowDependency,则 DAGScheduler 继续向前回溯;若 RDD 的依赖是 ShuffleDependency,DAGScheduler 便开启“三招一套”的招式,创建 Stage、注册 Stage 并继续向前回溯。由此可见,何时切割 DAG 并生成新的 Stage 由 RDD 的依赖类型决定,当且仅当 RDD 的依赖是 ShuffleDependency 时,DAGScheduler 才会新建 Stage。
喜欢刨根问底的您一定会问:“DAGScheduler 怎么知道 RDD 的依赖类型到底是哪一个?他怎么判别 RDD 的依赖是窄依赖还是 ShuffleDependency?”要回答这个问题,我们就还得回到 RDD 的 5 大属性上,不过这次出场的是 partitioner。还记得这个属性吗?partitioner 是 RDD 的分区器、定义了 RDD 数据分片的分区规则,它决定了 RDD 的数据分片在分布式集群中如何分布,这个属性至关重要,后面介绍 Shuffle 的时候我们还会提到它。DAGScheduler 正是通过 partitioner 来判定每个 RDD 的依赖类型,具体来说,如果子 RDD 的 partitioner 与父 RDD 的 partitioner 一致,那么 DAGScheduler 判定子 RDD 对父 RDD 的依赖属于窄依赖;相反,如果两者 partitioner 不一致,也即分区规则不同(分区规则不同则意味着一定存在数据的“重洗牌”,即 Shuffle),那么 DAGScheduler 判定子对父的依赖关系是 ShuffleDependency。到此,DAGScheduler 对于 DAG 的划分逻辑可以暂且告一段落。原理说了,例子举了,还缺啥?对!代码。
Show me the code
古人云:“光说不练假把式”,我们用一个小例子来展示一下 DAG 与 Stage 的关系。还是用上篇《内存计算的由来 —— RDD》中的 WordCount 依样画葫芦,文件内容如下。
示例文件内容
代码也没变:
WordCount 示例代码
虽然文件内容和代码都没变,但是我们观察问题的视角变了,这次我们关心的是 DAG 中 Stage 的划分以及 Stage 之间的关系。RDD 的 toDebugString 函数让我们可以一览 DAG 的构成以及 Stage 的划分,如下图所示。
DAG 构成及 Stage 划分
在上图中,从第 3 行往下,每一行表示一个 RDD,很显然,第 3 行的 ShuffledRDD 是 DAG 的尾节点,而第 7 行的 HadoopRDD 是首节点。我们来观察每一行字符串打印的特点,首先最明显地,第 4、5、6、7 行的前面都有个制表符(Tab),与第 3 行有个明显的错位,这表示第 3 行的 ShuffledRDD 被划分到了一个 Stage(记为 stage0),而第 4、5、6、7 行的其他 RDD 被划分到了另外一个 Stage(记为 stage1),且 stage0 对 stage1 有依赖关系。假设第 7 行下面的 RDD 字符串打印有两个制表符,即与第 7 行产生错位,那么第 7 行下面的 RDD 则被划到了新的 Stage,以此类推。
由此可见,通过 RDD 的 toDebugString 观察 DAG 的 Stage 划分时,制表符是个重要的指示牌。另外,我们看到第 3、4 行的开头都有个括号,括号里面是数字,这个数字标记的是 RDD 的 partitions 大小。当然了,观察 RDD、DAG、Stage 还有更直观的方式,Spark 的 Web UI 提供了更加丰富的可视化信息,不过 Spark 的 Web UI 面板繁多,对于新同学来说一眼望去反而容易不知所措,也许后面时间允许的话我们单开一篇 Spark Web UI 的串讲。
Postscript
本篇是《Spark 分布式计算科普专栏》的第二篇,笔者学浅才疏、疏漏难免。如果您有任何疑问,或是觉得文章中的描述有所遗漏或不妥,欢迎在评论区留言、讨论。掌握一门技术,书本中的知识往往只占两成,三成靠讨论,五成靠实践。更多的讨论能激发更多的观点、视角与洞察,也只有这样,对于一门技术的认知与理解才能更深入、牢固。
在本篇博文中,我们从 DAG 的边 —— Spark RDD 算子入手,介绍了衔接 RDD 的两大类算子:Transformations 和 Actions,并对惰性计算有了初步的认知。然后,还是以土豆工坊为例,介绍 DAGScheduler 切割 DAG、生成 Stage 的流程和步骤,尤其需要注意的是 DAGScheduler 以 Shuffle 为边界划分 Stage。
最后,用上一篇的 WordCount 简单展示了 DAG 与 Stage 的关系。细心的读者可能早已发现,文中多次提及“后文书再展开”、“后面再单开一篇”,Spark 是一个精妙而复杂的分布式计算引擎,在本篇博文中我们不得不对 Spark 中的许多概念都进行了“前置引用”。换句话说,有些概念还没来得及解释(如惰性计算、Shuffle、TaskScheduler、TaskSet、Spark 调度系统),就已经被引入到了本篇博文中。这样的叙述方法也许会给您带来困惑,毕竟,用一个还未说清楚的概念,去解释另一个新概念,总是感觉没那么牢靠。
常言道:“杀人偿命、欠债还钱”,在后续的专栏文章中,我们会继续对 Spark 的核心概念与原理进行探讨,慢慢地把欠您的技术债还上,尽可能地还原 Spark 分布式内存计算引擎的全貌。毕竟 Spark 调度系统为何方神圣,DAGScheduler 伙同 TaskScheduler、SchedulerBackend、TaskSetManager 等一众大佬如何演绎权利的游戏,且听下回分解。
作者简介
吴磊,Spark Summit China 2017 讲师、World AI Conference 2020 讲师,曾任职于 IBM、联想研究院、新浪微博,具备丰富的数据库、数据仓库、大数据开发与调优经验,主导基于海量数据的大规模机器学习框架的设计与实现。现担任 Comcast Freewheel 机器学习团队负责人,负责计算广告业务中机器学习应用的实践、落地与推广。热爱技术分享,热衷于从生活的视角解读技术,曾于《IBM developerWorks》和《程序员》杂志发表多篇技术文章。
延伸阅读:
深入浅出Spark(一):内存计算的由来-InfoQ
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |