Spark架构

本文对比了Spark和MapReduce的架构,解释了Spark如何克服MapReduce的局限性,如支持细粒度任务并行、利用多核CPU、中间结果缓存。Spark的提交过程涉及Driver、DAGScheduler和TaskScheduler,而MapReduce则包括Job对象的注册、资源分配和MapTask/ReduceTask的执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spark架构

在这里插入图片描述

  • MapReduceOnYarn(回顾)
    在这里插入图片描述工作步骤

    • 第一步:在ClientNode上,初始化JVM容器(RunJar),运行MapReduce应用,然后实例化Job对象
    • 第二步:将Job对象,注册到Yarn集群的ResourceManager之上,返回一个ApplicationId
    • 第三步:将Job对象的资源(任务的jar、配置文件、计算的数据切片信息等)提交到一个共享的文件系统(通常指的HDFS,大数据计算原则:移动计算而不移动数据)
    • 第四步:正式的将MapReduce的Job提交到Yarn计算中运行(注意:此步骤后所有的操作都发生在Yarn集群)
    • 第五、六步:Yarn集群的ResourceManager会在某空闲的NodeManager会加载一个JVM容器MRAppMaster(负责Job的监控和管理),并且对Job进行进一步的初始化
    • 第七步: MRAppMaster会从共享的文件系统(HDFS)获取数据切片信息,(一个Splits —》 MapTask, ReduceTask【默认为1,或者手动设定】)
    • 第八步:MRAppMaster会请求Yarn集群的ResourceManager分配相应单位的计算资源(JVM进程)
    • 第九步:MRAppMaster会在ResourceManager分配的空闲的NodeManager上启动相应单位的计算进程(YarnChild)
    • 第十、十一步:接下来YarnChild(Task JVM)会从共享的文件系统(HDFS)获取资源(任务jar包,计算数据),运行MapTask/ReduceTask
    • 第十二步: 当任务运行结束后,释放资源

    分析问题

    • MapReduce任务分为粗粒度的MapTask和ReduceTask,并且计算针对于进程(JVM)的,并不能发挥多核CPU的优势
    • MapReduce慢,MapTask映射的结果需要溢写在磁盘中存储,Reduce任务计算时需要通过网络从磁盘拉取负责计算分区数据,造成的大量资源开销
    • MapReduce完成复杂的科学计算,可能需要将多个任务串联起来,多个任务的数据通过HDFS这样的共享文件系统进行共享(MR—> R1 —> MR2 —> R2 —>MR3 —>R3 …), 计算延迟较高。本来就很慢,串联更慢。
    • MapReduce只能够进行Batch(大数据的批处理计算),不支持(Streaming,SQL【借助于Hive】、ML【借助于Mahout】等)
    • MapReduce计算中间结果不支持缓存(Cache)
  • SparkOnStandalone架构

将基于Spark开发的应用打包,提交到Standalone集群中运行

在这里插入图片描述

工作步骤

  • 第一步:在提交Spark应用时会初始化Driver(JVM进程),并且创建SparkContext
  • 第二步:Driver会根据任务需要的资源信息,请求资源管理器(ClusterManager)分配计算计算
  • 第三步:ClusterManager会根据将分配的计算资源反向注册给Driver
  • 第四步:Driver端的DAGScheduler划分Stage,将一个复杂的计算任务肢解为若个小的任务,每一个Stage阶段都包含一个TaskSet
  • 第五步:Driver端的TaskScheduler会根据阶段的划分,逐一提交Stage的TaskSet,运行在预支的计算节点。Spark计算节点在运行任务时,TaskSet中的每一个Task运行在Thread线程中,进行分布式并行计算。
  • 第六步:当所有阶段的任务运行结束后,通过SparkContext释放占用的计算资源,通知ClusterManager回收

总结特点

  • Spark可以将任务进行细粒度的拆分,每一个切分后的任务子集,都支持分布式并行计算。不同于MapReduce粗粒度的阶段划分
  • Spark任务在运行时针对线程的,不同于MapReduce进程,能够充分发挥多核CPU计算优势
  • Spark的Executor中有Cache缓冲区,可以将计算产生的中间结果进行缓存,便于重复计算和故障恢复。

Spark应用开发

依赖

<dependencies>
    <dependency>
        <groupId>org.apache.spark</groupId>
        <!--_scala的版本-->
        <artifactId>spark-core_2.11</artifactId>
        <version>2.4.4</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <!--scala项目的打包插件 spark application jar包 运行standalone集群-->
            <!--spark应用类似mr程序 运行集群环境中-->
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>4.0.1</version>
            <executions>
                <execution>
                    <id>scala-compile-first</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>add-source</goal>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

开发WordCount应用

import org.apache.spark.{SparkConf, SparkContext}

/**
  * spark版本的单词统计
  */
object WordCountApplication {
  def main(args: Array[String]): Unit = {
    //1. 创建SparkContext,上下文对象提供spark应用运行环境信息
    val conf = new SparkConf()
      .setAppName("WordCount Apps")
      .setMaster("spark://SparkOnStandalone:7077")

    val sc = new SparkContext(conf)

    //2. 编写DAG计算任务  有向无环图(某逻辑开发 --》 多重计算 --》最终输出)
    val rdd = sc.textFile("hdfs://SparkOnStandalone:9000/text.txt")

    val result = rdd
      .flatMap(line => line.split(" "))
      .map(word => (word, 1L)) // (Hello,1L)
      .groupByKey()
      .map(t2 => (t2._1, t2._2.size))

    result.saveAsTextFile("hdfs://SparkOnStandalone:9000/result")

    //3. 释放资源
    sc.stop()
  }
}

在Windows操作系统配置主机名映射

C:\Windows\System32\drivers\etc\HOSTS

192.168.126.100(主机IP)	SparkOnStandalone

将Spark应用打包集群运行(远程)

//1. 通过Maven Package插件将Spark应用 打成Jar包

//2. 将Jar包上传到虚拟机中

//3. 提交任务
[root@SparkOnStandalone spark-2.4.4]# bin/spark-submit --help
--master MASTER_URL  # 使用spark集群环境
--class CLASS_NAME   # spark应用入口类的全限定名
--total-executor-cores NUM # spark应用的计算进程占用核心数量Cores

如:
[root@SparkOnStandalone spark-2.4.4]# bin/spark-submit --master spark://SparkOnStandalone:7077 --class com.baizhi.WordCountApplication --total-executor-cores 2 /root/spark-day1-1.0-SNAPSHOT.jar

在Local本地模拟运行(本地)

import org.apache.spark.{SparkConf, SparkContext}

/**
  * spark版本的单词统计
  */
object WordCountApplicationOnLocal {
  def main(args: Array[String]): Unit = {
    //1. 创建SparkContext,上下文对象提供spark应用运行环境信息
    val conf = new SparkConf()
      .setAppName("WordCount Apps")
      .setMaster("local[*]")  // local 本地模式 模拟Spark应用运行 [*] 当前计算机的所有核心  cores 6

    val sc = new SparkContext(conf)

    //2. 编写DAG计算任务  有向无环图(某逻辑开发 --》 多重计算 --》最终输出)
    val rdd = sc.textFile("hdfs://SparkOnStandalone:9000/text.txt")

    val result = rdd
      .flatMap(line => line.split(" "))
      .map(word => (word, 1L)) // (Hello,1L)
      .groupByKey()
      .map(t2 => (t2._1, t2._2.size))

    result.saveAsTextFile("hdfs://SparkOnStandalone:9000/result")

    //3. 释放资源
    sc.stop()
  }
}

org.apache.hadoop.security.AccessControlException

解决方案

  • 在运行Spark应用时,添加虚拟机参数-DHADOOP_USER_NAME=root
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值