Spark学习

本文介绍了Spark的大规模数据处理原理,包括其基于DAG的任务调度、内存计算、多运行模式,以及Spark生态中的核心组件。详细阐述了Spark的RDD、DAG、Executor、Job、Stage和Task等基本概念,并分析了Spark的架构与任务执行流程,强调了其容错性和高效执行效率。此外,还提及了Spark SQL的发展和特性,以及Spark Streaming的延迟处理级别。

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

简介

基于DAG的任务调度执行机制,采用内存计算的方式,用于大规模数据处理的快速、通用引擎,尤其适用于迭代计算。

Spark具有运行模式多样的特点,可以独立部署在集群中,也可以运行在Hadoop集群中,可以部署在EC2云环境中。可以访问HDFS、Cassandra、HBase、Hive等多种数据源。

Spark生态主要包括Spark Core(数据处理引擎,也为其他组件提供基础数据处理组件)、Spark SQL(交互查询)、Spark Streaming(流数据处理)、MLLib和MLBase(机器学习)和GraphX(图计算)。

资源虚拟化管理(调度)方面可以使用Mesos或Yarn组件。详细的架构体系可查阅BDAS技术栈。

基本概念

RDD:弹性分布式数据集,分布式内存的抽象,提供一种调度受限的共享内存模型,;

DAG:有向无环图,反映 RDD间的依赖关系 (执行流程);

Executor:工作结点(WorkNode)上的进程,运行Task;

Application:用户编写的Spark程序;

Task:运行在Executor上的工作单元;

Job:一个Job包含多个RDD及作用于相应RDD上的操作;

Stage:Job的基本调度单位,一个Job可分为多组Task,每组Task就是一个Stage,或是TaskSet,代表一组关系的、相互之间没有Shuffle依赖关系的任务组成的任务集。

架构

Cluster Manager,负责集群资源管理,可使用Yarn或Mesos来作为资源管理器的执行组件;

Driver,是任务控制节点,负责任务分解、生成DAG、DAG的优化、DAG中任务的分配等,是集群的管家

WorkNode,负责运行具体的作业任务,每个WorkNode可以有多个Executor(执行进程),由Executor复用多线程进行Task的处理,而且Executor中的BlockManager会对内存和磁盘进行统一管理(RDD就是通过BlockManager的管理,优先写入内存中,当内存不足时,再写入磁盘),将内存和磁盘共同作为存储设备,以减少IO。

层次关系是:每个Application包含一个Driver及多个Job,每个Job包含若干Stage,每个stage包含若干Task,task在Executor中执行。

执行过程中,Driver先生成一个SparkContext用于后续的任务分解、流程(DAG Scheduler)和计划(TaskScheduler)的制定与任务管理,然后向集群管理器申请资源,并在资源中启动Executor,Executor启动后会主动向SparkContext进行注册和任务申请,TaskScheduler会将任务及程序代码发送给Executor,然后在Executor上执行Task,Executor执行结束后,将结果返回Driver中SparkContext的TaskScheduler,然后再向上层的DAG Scheduler反馈,最后写入HDFS或数据库。

RDD

RDD是一个只读的分区记录集合,RDD的不同分区会被存储到集群的不同节点上去,从而实现在集群中不同节点上的并行计算。RDD中的数据只有在创建和转换的过程中进行调整,一旦数据进入RDD则不能再修改。

RDD在执行过程中,首先会读入数据,并进行数据分区,形成RDD,然后经过一系列转换操作(后由Driver生成DAG流程图,即RDD的血缘关系),直至最后调用一个动作,对数据进行处理,在整个过程中,直至“动作”操作之前,所有的转换过程都不会写入磁盘(除非内存不足了),这样就实现了数据流式的连续操作,减少IO操作的同时,也消除了由于序列化和反序列化带来的开销,以优化整体的执行效率。

RDD血缘关系的设计使Spark具有很好的容错性,哪里出错,重新执行上一步的操作即可。

RDD的窄依赖:一个父RDD的分区,只对应一个子RDD分区或多个父RDD分区对应一个子RDD分区;(一对一或多对一,map

/filter、union、join)

宽依赖:一个父RDD的分区对应一个子RDD的多个分区。(一对多或多对多,groupByKey、join).

Spark通过分析RDD的依赖关系生成DAG,然后再根据RDD内各分区的宽窄依赖关系来划分Stage:

对DAG进行反向解析,一量遇到宽依赖就断开(宽依赖会涉及Shuffle操作),遇到窄依赖就把当前RDD放入一个stage中,将窄依赖放入同一stage,可实现数据的流水线式作业。

Stage可分为ShuffleMapStage和ResultStage。ShuffleMapStage是过程Stage,它的输出结果会经过Shuffle过程作为后续Stage(任何类型的Stage)的输入。ShuffleMapStage的输入可能是外部读入的数据或是其它ShuffleMapStage的输出,每个Job中可能有0到多个ShuffleMapStage;ResultStage是最终的Stage,没有输出,直接产生结果或存储。ResultStage的输入可能是外部读入的数据或是其它ShuffleMapStage的输出,每个Job中至少有一个ResultStage类型的Stage。

RDD的运行过程:

1.创建RDD对象

2.SparkContext计算RDD间依赖关系,构建DAG;

3.DAG Scheduler分解DAG为多个Stage,每个Stage包含1到多个Task,每个Task被TaskScheduler分发给各个WN上的Executor执行。

Spark SQL

Shark(Hive on spark)可以看作是Spark SQL的前身,在Shark中只是对Hive底层的MR计算框架替换为了Spark计算框架。但这样也就遗留了一些问题,如优化策略依赖于hive,无法添加新的优化策略,以及spark是线程级并行,在兼容Hive时,面临线程安全的问题(Hive所依赖的MR是进程级并行)等;Spark SQL延用了Hive的解析器和元数据管理,执行计划和优化由Catalyst完成,其余部分也都根据Spark框架重写。

Spark SQL中增加了SchemaRDD,使Spark SQL的数据源可以是来源于RDD,也可以是Hive、HDFS、Cassandra或Json格式的外部数据,支持的数据类型更多。支持Scala、java、python开发。

支持Standalone、Mesos和Yarn三种部署方式。

SparkStreaming无法做到毫秒级的响应而是秒级的响应,本质上它还是属于小数据集的处理。毫秒级的响应仍然需要使用Storm。

### Spark Java 开发入门教程 Apache Spark 是一个强大的分布式计算框架,支持多种编程语言,包括 Java。以下是学习如何在 Java 中使用 Spark 进行开发的步骤关键点。 #### 环境搭建 首先,需要准备好开发环境。推荐的操作系统是 Windows 11 或者 Linux,开发工具可以使用 IntelliJ IDEA 2023.2.5,并且需要安装 JDK 1.8(如 Corretto-1.8.0_392)[^2]。此外,还需要下载 Hadoop,因为 Spark 通常与 Hadoop 配合使用以处理大规模数据集。可以从 [Hadoop 下载页面](https://hadoop.apache.org/releases.html) 获取最新版本的 Hadoop,例如 `hadoop-3.3.6`。 #### 创建项目 创建一个新的 Maven 项目来组织你的代码。Maven 提供了方便的方式来管理依赖项构建过程。你需要在项目的 `pom.xml` 文件中添加 Spark 的依赖项。以下是一个示例配置: ```xml <dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.12</artifactId> <version>3.4.0</version> </dependency> </dependencies> ``` #### 编写第一个 Spark 应用程序 下面是一个简单的 Spark 应用程序,它读取一个文本文件并统计每个单词出现的次数。这个例子展示了如何创建一个 Spark 应用程序的基本结构。 ```java import org.apache.spark.sql.SparkSession; import java.util.Arrays; import org.apache.spark.api.java.JavaRDD; import scala.Tuple2; public class FirstSparkApp { public static void main(String[] args) { // 创建SparkSession SparkSession spark = SparkSession.builder() .appName("MyFirstSparkApp") .master("local") // 使用本地模式 .getOrCreate(); // 加载文本文件作为RDD JavaRDD<String> lines = spark.read().textFile("README.md").javaRDD(); // 统计每个单词出现次数 JavaRDD<String> words = lines.flatMap(line -> Arrays.asList(line.split(" ")).iterator()); JavaPairRDD<String, Integer> pairs = words.mapToPair(word -> new Tuple2<>(word, 1)); JavaPairRDD<String, Integer> counts = pairs.reduceByKey((a, b) -> a + b); // 打印结果 counts.collect().forEach(System.out::println); // 关闭SparkSession spark.stop(); } } ``` #### 构建运行应用程序 构建项目时,可以使用 Maven 命令 `mvn clean package` 来编译打包项目。之后,可以通过以下命令运行应用程序: ```bash java -cp target/spark-java-integration-1.0-SNAPSHOT.jar com.example.WordCountApp ``` 确保你已经正确设置了类路径,并且所有的依赖项都已经被包含在内。 #### 调试测试 调试 Spark 应用程序时,可以在本地模式下运行,这样可以在 IDE 中直接调试。如果遇到问题,检查日志输出是非常重要的。常见的问题包括类路径错误、依赖项缺失或配置不当。 #### 学习资源 为了进一步学习 Apache Spark Java 开发,可以参考官方文档其他在线资源。Apache Spark 官方网站提供了详细的文档支持材料,可以帮助开发者更好地理解使用 Spark。中文资料也可以访问 [Apache Spark 中文官网](https://spark.apachecn.org/)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值