SparkCore入门编程

本文详细介绍了Spark的概述,包括与Hadoop的比较、Spark的入门编程、安装部署过程,以及核心编程概念如RDD、转换和行动算子。通过实例展示了wordcount的编写、RDD的获取和操作,以及Spark的安装部署,包括Local模式、Standalone集群模式、YARN模式的配置和应用。此外,还涵盖了Spark的架构、序列化、依赖关系、缓存持久化和shuffle机制。

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

一、Spark的概述

1.1 Hadoop的回顾

  • 版本号的发展
hadoop1.x  : hdfs 和 mapreduce   

hadoop2.x  : hdfs、mapreduce、yarn、common   

hadoop3.x  : hdfs、mapreduce、yarn、common  
  • hadoop的重要模块组成
hdfs  :  分布式文件存储系统       需要搭建和部署
mapreduce:  离线分析和计算框架    不需要搭建, 是程序要要开发的逻辑代码
yarn :   资源调度管理系统         需要搭建和部署
  • HDFS的优点和缺点
优点:
	-- datanode的可靠性、可以部署在廉价的商用硬件上(允许部分机器宕机)
   -- 适合存储大数据集
	-- 副本自动冗余策略(不满足3个的时候,会自动启动冗余,达到3个)
	-- 集群易于横向扩展(增加节点)
缺点:
	-- 不适合存储小文件
   -- 只支持追加操作
   -- 在同一时间内只允许一个writer
  • MR的优点和缺点
优点:
   -- 适合批处理(离线处理)计算大数据集
   -- 易于编程
   -- 容错性较好(task失败,可以进行重试)
   -- 扩展性良好
缺点:
   --  不适合低延迟的工作
   --  不适合处理小文件
   --  调优困难

1.2 Spark的简介

1.2.1 Spark是什么

-1. spark是一个快速的、通用的、可扩展的大数据分析计算框架
-2. spark是用scala语言编写的
-3. spark在09年诞生、13年6月加入apache、14年2月成为顶级项目
-4. Spark快的原因:
		(1)基于内存计算
		(2)使用DAG执行引擎(调度)
		(3)支持数据向上追踪(血缘追踪,临时存储)
-5. spark可以进行 批处理、迭代运算、交互式查询、流处理、机器学习、图处理等
-6. spark程序可以使用多种语言编写,比如java、scala、python、r语言等
-7. spark能处理的数据源,也比较多,比如可以处理mysql、hdfs、hive等各种地方的数据
-8. spark的安装部署方式有多种
	    本地模式:  local
	    集群模式: standalone、yarn、mesos、k8s

1.2.2 Spark的模块组件

  • Spark Core
实现了 Spark 的基本功能,包含任务调度、内存管理、错误恢复、与存储系统 交互等模块。Spark Core 中还包含了对弹性分布式数据集(resilient distributed dataset,简称RDD)的 API 定义。 
  • Spark SQL
是 Spark 用来操作结构化数据的程序包。通过 Spark SQL,我们可以使用 SQL 或者 Apache Hive 版本的 SQL 方言(HQL)来查询数据。Spark SQL 支持多种数据源,比 如 Hive 表、Parquet 以及 JSON 等。 
  • Spark Streaming
是 Spark 提供的对实时数据进行流式计算的组件。提供了用来操作数据流的 API,并且与 Spark Core 中的 RDD API 高度对应。
  • Spark MLlib
提供常见的机器学习(ML)功能的程序库。包括分类、回归、聚类、协同过滤等,还提供了模型评估、数据 导入等额外的支持功能。
  • Spark GraphX
GraphX在Spark基础上提供了一站式的数据解决方案,可以高效地完成图计算的完整流水作业。GraphX是用于图计算和并行图计算的新的(alpha)Spark API。通过引入弹性分布式属性图(Resilient Distributed Property Graph),一种顶点和边都带有属性的有向多重图,扩展了Spark RDD。

1.3 Spark与Hadoop的比较

1.3.1 框架比较

hadoop spark
起源 2005 2009
起源地 MapReduce (Google) Hadoop (Yahoo) University of California, Berkeley
数据处理引擎 Batch Batch
处理 Slower than Spark and Flink 100x Faster than Hadoop
编程语言 Java, C, C++, Ruby, Groovy, Perl, Python Java, Scala, python and R
编程模型 MapReduce Resilient distributed Datasets (RDD)
Data Transfer Batch Batch
内存管理 Disk Based JVM Managed
延迟 HIgh Medium
吞吐量 Medium High
优化机制 Manual Manual
API Low-level High-level
流处理支持 NA Spark Streaming
SQL支持 Hive, Impala SparkSQL
Graph 支持 NA GraphX
机器学习支持 NA SparkML

1.3.2 处理流程比较

1)MR中的迭代:

在这里插入图片描述

mr的整个应用程序,通常会有多个job串联, 在整个应用程序处理过程中,一个job所需要的数据使从磁盘上读取的,job执行完,会将处理结果存储到磁盘上,因此整个作业的迭代,涉及到大量的磁盘IO,所以慢

2)Spark中的迭代:

在这里插入图片描述

spark整个应用程序,也会有多个job串联,在处理过程中,第一个job从磁盘上读取数据,处理结果通常情况下存储到内存里,下一个job从内存中读取数据,进行处理,依次执行下去。所以说,整个作业的迭代,通常都是基于内存的,因此处理速度更快。

1.4 Spark的入门编程

说明:

创建maven项目,引入下面的jar包依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spark_sz2102</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!-- 声明公有的属性 -->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <encoding>UTF-8</encoding>
        <scala.version>2.11.8</scala.version>
        <spark.version>2.2.3</spark.version>
        <hadoop.version>2.7.6</hadoop.version>
        <scala.compat.version>2.11</scala.compat.version>
    </properties>
    <!-- 声明并引入公有的依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>${scala.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
    </dependencies>

    <!-- 配置构建信息 -->
    <build>
        <!-- 资源文件夹 -->
        <sourceDirectory>src/main/scala</sourceDirectory>
        <!-- 声明并引入构建的插件 -->
        <plugins>
            <!-- 用于编译Scala代码到class -->
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <args>
                                <arg>-dependencyfile</arg>
                                <arg>${project.build.directory}/.scala_dependencies</arg>
                            </args>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- 程序打包 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <!-- 过滤掉以下文件,不打包 :解决包重复引用导致的打包错误-->
                            <filters>
                                <filter><artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <transformers>
                                <!-- 打成可执行的jar包 的主方法入口-->
                                <transformer  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass></mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

1.4.1 wordcount的编写方式1

1)编程思路
在这里插入图片描述

1:按行读取数据,2:按照空格切分成单词 3:按照单词分组 4:统计每组的单词个数

2)代码实现

package com.qf.sparkcore.day01

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

/**
 * spark的入门案例: wordcount
 * 思路:
 *    1:按行读取数据,2:按照空格切分成单词 3:按照单词分组 4:统计每组的单词个数
 */
object WordCount1 {
   
    def main(args: Array[String]): Unit = {
   
        //1: 构建配置对象, 获取spark上下文对象
        val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("wordcount")
        val sc: SparkContext = new SparkContext(conf)

        //2:  读取数据    RDD[String] : 指代的就是多个String的弹性分布式数据集   每个String都是一行记录。
        val lines: RDD[String] = sc.textFile("D:/data/")
        //3: 按照空格切分,并展平  [spark,core,hello.......]
        val words: RDD[String] = lines.flatMap((line) => line.split(" "))
        //4: 按照单词分组   每个元素都是一个具有两个元素的元组  第一个元素是单词 第二个元素是这个单词的集合,
        //   比如  (spark,List(spark,spark,spark))   (hello,List(hello,hello,hello))......
        val wordGroup: RDD[(String, Iterable[String])] = words.groupBy(word => word)
        //5:统计每一组的个数
        val wordAndCount: RDD[(String, Int)] = wordGroup.mapValues(_.size)
        //6: 将分布在各个计算节点的RDD搜集到客户端,并打印
        val result: Array[(String, Int)] = wordAndCount.collect()
        result.foreach(println)

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

1.4.2 wordcount的编写方式2

1)编程思路

在这里插入图片描述

1:按行读取数据,2:按照空格切分成单词 3:构建元素 4:按照单词分组 5:统计每一组中的1的和

2)代码实现

package com.qf.sparkcore.day01

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

/**
 * spark的入门案例: wordcount
 * 思路2:
 *    1:按行读取数据,2:按照空格切分成单词 3:构建元素 4:按照单词分组 5:统计每一组中的1的和
 */
object WordCount2 {
   
    def main(args: Array[String]): Unit = {
   
        //1: 构建配置对象, 获取spark上下文对象
        val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("wordcount")
        val sc: SparkContext = new SparkContext(conf)

        //2:  读取数据    RDD[String] : 指代的就是多个String的弹性分布式数据集   每个String都是一行记录。
        val lines: RDD[String] = sc.textFile("D:/data/")
        //3: 按照空格切分,并展平  [spark,core,hello.......]
        val words: RDD[String] = lines.flatMap((line) => line.split(" "))
        //4: 将每个单词和1 构建一个kv形式的元组   (spark,1) (core,1) (hello,1) (spark,1)........
        val wordAndOne: RDD[(String, Int)] = words.map((_, 1))

       /* //5: 按照元组的第一个元素即单词分组:  (spark,List((spark,1),(spark,1),(spark,1)) (hello,List((hello,1),(hello,1),(hello,1)))....
        val wordAndList: RDD[(String, Iterable[(String, Int)])] = wordAndOne.groupBy(_._1)
        //6: 统计每一组中的1的累加值
        val wordAndCount: RDD[(String, Int)] = wordAndList.map(group => {
            val list: Iterable[(String, Int)] = group._2
            var sum = 0;
            for (elem <- list) {
                sum += elem._2
            }
            (group._1, sum)
        })*/

        /**
         *  5 : 使用reduceByKey直接计算
         *      前提:元素必须是KV形式的数据
         *      作用: 通过k进行分组,并对value进行聚合  。   也就是将同一个k的分为一组,然后将同一组的所有value进行reduce
         *      参数:func:(Int,Int) =>Int      是一个函数:
         *                                     函数的第一个参数接受这一组所有value的第一个value,并进行累加
         *                                     函数的第二个参数接受这一组所有value除了第一个value的其他value  依次累加到第一个value上
         *     (spark,(1,1,1))  (hello,(1,1,1))....
         *     (spark,3)   (hello,3).....
         */
        val wordAndCount: RDD[(String, Int)] = wordAndOne.reduceByKey(_ + _)

        //6: 搜集,打印
        val result: Array[(String, Int)] = wordAndCount.collect()
        result.foreach(println)

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

1.4.3 日志文件的引入

我们的目的,程序正确时,控制台只打印结果,错误时,打印错误级别的信息

在项目的resources目录下,创建文件log4j.properties,存入下面的内容

# Set everything to be logged to the console
log4j.rootCategory=ERROR, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n

# Set the default spark-shell log level to WARN. When running the spark-shell, the
# log level for this class is used to overwrite the root logger's log level, so that
# the user can have different defaults for the shell and regular Spark apps.
log4j.logger.org.apache.spark.repl.Main=WARN

# Settings to quiet third party logs that are too verbose
log4j.logger.org.spark_project.jetty=WARN
log4j.logger.org.spark_project.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
log4j.logger.org.apache.parquet=ERROR
log4j.logger.parquet=ERROR

# SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support
log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=FATAL
log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry=ERROR

二、Spark的安装部署

注意,注意,注意: spark在部署时, 不建议配置环境变量

2.1 安装部署的模式介绍

Spark的安装模式指的是运行spark程序时所需要的资源调度管理系统。

资源调度管理系统有两类,一种是本地模式,一种是集群模式。

1. 本地模式:  local模式
	指的是利用运行程序所在的那一台机器的系统平台, 
   比如在windows运行,利用的就是本地的windows系统
       在linux运行,用的就是本地的windows系统
	    在mac运行,用的就是本地的mac系统
    作用,用于开发人员测试、调试代码等,
2. 集群模式:
	- Standalone:  
		 spark本身自带的一个资源调度系统,也分为单机和集群模式
	- yarn:
		 spark利用hadoop的yarn资源调度系统,进行spark程序的资源调度
		 在国内用的是最多的
	- mesos:
		 这是一款在国外比较流行的资源调度系统
	- k8s:
		 这个也是一种资源调度系统,出名的公司一般会用这个。

2.2 Spark的Local模式

1)上传、解压、更名

[root@qianfeng01 ~]# tar -zxvf spark-2.2.3-bin-hadoop2.7.tgz -C /usr/local/
[root@qianfeng01 ~]# cd /usr/local/
[root@qianfeng01 local]# mv spark-2.2.3-bin-hadoop2.7/ spark-local

2)启动,进入scala交互界面

[root@qianfeng01 local]# cd spark-local
[root@qianfeng01 spark-local]# ./bin/spark-shell

小贴士: 只要运行spark-shell脚本,进入scala交互界面,即成功

3)程序测试:

1. 在spark-local下的data目录,创建一个words.txt文件
hello spark
hello world
hello java
hello spark
2. 在spark-local目录下启动spark-shell指令
  [root@qianfeng01 spark-local]# ./bin/spark-shell
3. 进入scala交互界面后,有两个变量可以直接使用,一个是sc(spark上下文),一个是spark(SparkSession) 
  scala> sc.textFile("data/words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect().foreach(println)

(java,1)
(hello,4)
(world,1)
(spark,2)

2.3 Standalone集群模式

2.3.1 简要说明

standalone指的是spark程序自带的一个资源调度管理系统。支持集群模式,也支持单机模式。不管是什么模式,他都是一个主从架构,即一个活跃的master和N个worker.

master守护进程是一个管理节点,worker守护进程,有多个,是工作节点

部署安排

qianfeng01: master   worker
qianfeng02:	worker
qianfeng03: worker

准备条件:

三台机器的免密登录认证、防火墙关闭、时间同步、jdk1.8+,hadoop2.7.6

2.3.2 安装部署

1)上传、解压、更名

[root@qianfeng01 ~]# tar -zxvf spark-2.2.3-bin-hadoop2.7.tgz -C /usr/local/
[root@qianfeng01 ~]# cd /usr/local/
[root@qianfeng01 local]# mv spark-2.2.3-bin-hadoop2.7/ spark-standalone

PS: 如果想要使用多种模式的话,不建议配置环境变量,

2)配置spark的环境脚本

[root@qianfeng01 ~]# cd /usr/local/spark-standalone/conf/
[root@qianfeng01 conf]# cp spark-env.sh.template spark-env.sh
[root@qianfeng01 conf]# vim spark-env.sh
.......在文件末尾添加如下内容..........
export JAVA_HOME=/usr/local/jdk
export SPARK_MASTER_HOST=qianfeng01
export SPARK_MASTER_PORT=7077


解析:
   环境变量SPARK_MASTER_HOST或SPARK_MASTER_IP,这两个任选其一,如果使host那就配置主机名,如果使ip就配置相关IP
   7077 是master的端口号,用于内部组件之间的通信

3)配置slaves文件,即工作节点的主机名

[root@qianfeng01 conf]# cp slaves.template slaves
[root@qianfeng01 conf]# vim slaves
qianfeng01
qianfeng02
qianfeng03
  1. 分发到其他节点
[root@qianfeng01 ~]# scp -r /usr/local/spark-standalone/ qianfeng02:/usr/local/
[root@qianfeng01 ~]# scp -r /usr/local/spark-standalone/ qianfeng03:/usr/local/

5) 启动测试

[root@qianfeng01 spark-standalone]# ./sbin/start-all.sh

注意: 
1. 查看进程是否已经启动
   jps
2. 如果没有成功,需要查看日志,在spark自己的logs目录下   

6)查看webUI

在浏览器上输入:
http://qianfeng01:8080

7)端口号的总结:

7077:   worker和master通信的端口号
8080:   master的webui端口
4040:  spark-shell交互平台的一个历史作业的webui

8088:  yarn的webui端口
50070:  namenode的webui端口
8020:  datanode和namenode的端口
16010:  hmaster的webui端口

2.3.3 spark-shell脚本的应用

该脚本为spark提供了一个交互式平台,可以在此进行spark编程,以及调节spark程序。

运行模式有两种:一种是本地模式,一种是集群模式

1)本地模式的运行:

直接在命令行上输入
[root@qianfeng01 spark-standalone]# ./bin/spark-shell

在这里插入图片描述

2)集群模式的运行

[root@qianfeng01 ~]# /usr/local/spark-standalone/bin/spark-shell \
--master spark://qianfeng01:7077 \
--executor-memory 512m \
--total-executor-cores 1 

注意:集群模式,必须指定master,其他属性可选

在这里插入图片描述

3)退出交互界面

正规方式:
:quit
:q

尽量不要用ctrl + c,有可能会造成4040依然被占用,也就使没有完全退出,
如果不小心ctrl+c,没有完全退出,使用命令查看监听端口 netstat - apn | grep 4040 在使用kill -9 端口号 杀死即可   

2.3.4 配置Job History Server

1)说明

因为在spark程序运行期间,driver会提供webui界面,来监控并显示运行状态。但是如果程序运行完,Driver会停止该webui界面的通信,就看不到之前的运行信息了。
如果想要查看原来的运行信息,可以配置作业历史服务器,将作业运行状态信息保存到HDFS上

2)配置如下

1. 启动HDFS、在HDFS上创建一个目录,用于存储spark作业的历史记录
   [root@qianfeng01 ~]# start-dfs.sh
   [root@qianfeng01 ~]# hdfs dfs -mkdir /sparkJobHistory
2. 修改spark的spark-default.conf文件
   [root@qianfeng01 ~]# cd /usr/local/spark-standalone/conf
   [root@qianfeng01 conf]# cp spark-defaults.conf.template spark-defaults.conf
   [root@qianfeng01 conf]# vim spark-defaults.conf
   ......
   #开启历史服务
   spark.eventLog.enabled           true   
   #存储路径
   spark.eventLog.dir               hdfs://qianfeng01:8020/sparkJobHistory
   #是否压缩
   spark.eventLog.compress          true 
3. 修改spark-env.sh文件,添加如下配置
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=4000 -Dspark.history.retainedApplications=10 -Dspark.history.fs.logDirectory=hdfs://qianfeng01:8020/sparkJobHistory"

4. 分发两个配置文件到其他节点
[root@qianfeng01 conf]# scp -r ./spark-env.sh ./spark-defaults.conf root@qianfeng02:$PWD
[root@qianfeng01 conf]# scp -r ./spark-env.sh ./spark-defaults.conf root@qianfeng03:$PWD


5. 启动历史服务器
   先启动spark,
    /usr/local/spark-standalone/sbin/start-all.sh   
    然后启动历史服务器
    /usr/local/spark-standalone/sbin/start-history-server.sh 
6. 查看进程
    [root@qianfeng01 conf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值