我试图深入了解火花洗牌过程。当我开始阅读时,我遇到了以下几点。
Spark 在完成后将 Map 任务(ShuffleMapTask)输出直接写入磁盘。
我想了解Hadoop MapReduce的以下内容。
-
如果Map-Reduce和Spark都将数据写入本地磁盘,那么Spark shuffle过程与Hadoop MapReduce有何不同?
-
既然数据在Spark中表示为RDD,为什么这些输出不保留在节点执行器内存中?
-
Hadoop MapReduce和Spark的Map任务输出有何不同?
-
如果有很多小中间文件作为输出,spark 如何处理网络和 I/O 瓶颈?
首先,Spark 不会以严格的 map-reduce 方式工作map
除非必要,否则输出不会写入磁盘。写入磁盘的是写入的随机文件。
这并不意味着随机播放后的数据不会保留在内存中。Spark 中的随机文件主要是为了避免在多个下游操作的情况下重新计算。为什么要写入文件系统?至少有两个交错的原因:
- 内存
- 是一种宝贵的资源,Spark 中的内存中缓存是短暂的。可以在需要时从缓存中逐出旧数据。
- 如果没有必要,洗牌是一个昂贵的过程,我们希望避免。存储随机数据的方式使其在给定上下文的生存期内持久化更有意义。
Shuffle本身,除了正在进行的低级优化工作和实现细节之外,根本没有什么不同。它基于相同的基本方法,但有其所有局限性。
任务与Hadoo地图有何不同?正如贾斯汀·皮霍尼(Justin Pihony)所很好地说明的那样,不需要洗牌的多个转换在单个任务中被挤压在一起。由于这些在标准 Scala 迭代器上运行,因此可以管道对单个元素进行操作。
关于网络和 I/O 瓶颈,这里没有灵丹妙药。虽然 Spark 可以通过组合转换、内存缓存和提供转换感知工作线程首选项来减少写入磁盘或洗牌的数据量,但它与任何其他分布式框架一样受到相同的限制。
如果Map-Reduce和Spark都将数据写入本地磁盘,那么Spark shuffle过程与Hadoop MapReduce有何不同?
当您执行 Spark 应用程序时,第一件事是首先启动SparkContext
,它成为多个互连服务的家园,其中DAGScheduler
、TaskScheduler
和SchedulerBackend
是最重要的服务之一。
DAGScheduler
是主要的编排器,负责将 RDD 谱系图(即 RDD 的有向无环图)转换为阶段。在执行此操作时,DAGScheduler
遍历最终RDD的父依赖项,并使用父ShuffleMapStages
创建ResultStage
。
ResultStage
(大部分)是最后阶段,ShuffleMapStages
是它的父母。我说主要是因为我想我可能已经看到你可以"安排"一个ShuffleMapStage
。
这是 Spark 应用于 Spark 作业(共同创建 Spark 应用程序)的早期和第一个优化 - 执行流水线,其中多个转换连接在一起以创建单个阶段(因为它们的相互依赖关系很窄)。这就是Spark比Hadoop MapReduce更快的原因,因为两个或多个转换可以一个接一个地执行,而没有数据洗牌可能全部在内存中。
单个阶段在达到ShuffleDependency
之前是相同的宽(也称为宽依赖)。
有些 RDD 转换会导致洗牌(由于创建 ShuffleDependency
)。这就是Spark非常像Hadoop的MapReduce的时刻,因为它会将部分随机输出保存到...执行程序上的本地磁盘。
当Spark应用程序启动时,它会从集群管理器请求执行器(支持三种:Spark Standalone,Apache Mesos和Hadoop YARN)。这就是SchedulerBackend
用途 - 管理 Spark 应用程序和群集资源之间的通信。
(假设您没有使用外部随机播放管理器)
执行程序托管自己的本地BlockManager
,负责管理保存在本地硬盘驱动器上的RDD块(可能在内存中并复制)。您可以使用cache
和persist
运算符以及存储级别来控制RDD块持久性。您可以使用 Web UI 中的Storage
和Executors
选项卡来跟踪块的位置和大小。
Spark在本地(在执行器上)存储数据与Hadoop MapReduce之间的区别在于:
-
部分结果(计算
ShuffleMapStages
后)保存在本地硬盘驱动器上,而不是HDFS,HDFS是一个分布式文件系统,保存成本非常高。 -
只有一些文件被保存到本地硬盘驱动器(在操作流水线之后),这在Hadoop MapReduce中不会发生,Hadoop MapReduce将所有映射保存到HDFS。
让我回答以下问题:
如果有很多小中间文件作为输出,spark 如何处理网络和 I/O 瓶颈?
这是Spark执行计划中最棘手的部分,很大程度上取决于洗牌的范围。如果仅使用本地数据(一台计算机上的多个执行程序),则不会看到任何数据流量,因为数据已经就位。
如果需要数据随机播放,执行程序将在彼此之间发送数据,这将增加流量。
Spark应用程序中节点之间的数据交换
只是为了详细说明Spark应用程序中节点之间的流量。
广播变量是将数据从驱动程序发送到执行程序的方法。
累加器是将数据从执行器发送到驱动程序的方法。
像 collect 这样的操作员会将所有远程块从执行器拉到驱动程序。