Spark_Day01
文章目录
Spark的介绍
-
What is Spark?
-
Apache Spark is an open source cluster computing system that aims to make data analytics fast
-
Both fast to run and fast to wrtie
-
Spark 是专为大规模数据处理而设计的快速通用的计算引擎
-
Spark 可以完成各种运算,包括 SQL 查询、文本处理、机器学习等
-
Spark由Scala语言开发,能够和Scala紧密结合
Spark的发展历史
Spark的组件
Spark包括以下几个部分:
-
Spark Core 核心底层部分
- 基于RDD
- 支持多种语言
-
Spark SQL
- 基于DataFrame
- 结构化数据查询
-
Spark Streming 流处理
-
Spark MLLib 机器学习
-
Spark GraphX 图计算
Spark和MapReduce的对比
- 从开发成本上看
- Spark开发效率高,开发成本低
- MapReduce开发效率低,开发成本高
- 从资源占用和释放的情况上看
- Spark任务运行在同一个进程空间,占用同一块资源,假设两个任务在同一块进程空间运行,第一个任务运行完毕之后,其所占用的资源得到释放,第二个任务独享整个进程空间的资源直到其执行完毕才释放资源
- MapReduce的任务是进程级别的,假设有map和reduce两个任务正在运行,map任务运行完毕之后释放其占用的进程资源,而reduce任务占用的资源没有变化,依然是其任务所在的进程空间的资源
- 从任务粒度上看
- Spark是多线程模式,任务启动速度和切换速度快,适合低延迟任务,任务在同一进程空间,共享该空间的内存,适合内存密集型任务,同节点所在的任务JVM中,被进程占用的数据可以反复调用,但是任务运行会出现严重的资源竞争,且基于内存断电丢失,稳定性不强
- MapReduce是多进程模式,启动时间长,不适合做低延迟任务,但各个进程之间是隔离的,且基于磁盘,保证了任务的稳定性
Spark部署方式
Spark支持多种部署模式
-
Local本地模式
- 多用于开发、本地测试
-
Standalone
- Spark自带的资源管理框架
- 可独立于其他大数据组件运行
-
Mesos
- 开源的资源管理系统
- 支持各种应用
-
Kubernetes
- Google开源的一个容器编排引擎
- 可移植、可拓展、自动化
-
Yarn
- Hadoop自带资源管理框架
- 贴合大数据生态
- 更具前景
使用Spark本地模式编写WordCount代码
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Demo1WCT {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
conf.setMaster("local")
conf.setAppName("Demo1WCT")
val sc: SparkContext = new SparkContext(conf)
val value: RDD[String] = sc.textFile("src/data/data/words.txt")
value.flatMap(_.split(","))
.groupBy( word => word)
.map(kv => {
(kv._1,kv._2.size)
})
.foreach(println)
}
}
Spark搭建
Local模式
主要用于本地开发测试
本文档主要介绍如何在IDEA中配置Spark开发环境
-
打开IDEA,创建Maven项目
-
在IDEA设置中安装Scala插件
-
在pom.xml文件中添加Scala依赖
<dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>2.12.10</version> </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-compiler</artifactId> <version>2.12.10</version> </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-reflect</artifactId> <version>2.12.10</version> </dependency>
-
在pom.xml中添加Scala编译插件
需要加在build->plugins标签下
<!-- Scala Compiler --> <plugin> <groupId>org.scala-tools</groupId> <artifactId>maven-scala-plugin</artifactId> <version>2.15.2</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin>
-
在pom.xml文件中添加Spark-Core依赖
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>3.1.3</version> </dependency>
-
编写第一个Spark程序
-
准备words.txt数据,每一行包含多个单词,单词之间以逗号分隔
java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop java,spark,java,hadoop
-
编写代码
注意words.txt文件路径,按自身情况修改
package com.shujia.core import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object Demo01WordCount { def main(args: Array[String]): Unit = { // 1、构建Spark环境 // 配置Spark任务 val conf: SparkConf = new SparkConf() conf.setAppName("Demo01WordCount") // 设置任务名 conf.setMaster("local") // 设置Spark的运行方式 // 创建SparkContext --> Spark程序的入口 val sc: SparkContext = new SparkContext(conf) // 2、构建Spark程序 // 加载数据 val lineRDD: RDD[String] = sc.textFile("spark/data/words.txt") // 将每个单词提取出来 val wordsRDD: RDD[String] = lineRDD.flatMap(_.split(",")) // 按每个单词进行分组 val groupRDD: RDD[(String, Iterable[String])] = wordsRDD.groupBy(word => word) // 统计每个单词的数量 val wordCntRDD: RDD[String] = groupRDD.map(kv => s"${kv._1},${kv._2.size}") // 将结果输出 wordCntRDD.foreach(println) } }
-
右键运行,结果如下
-
-
常见错误
-
windows环境下运行任务通常会有如下报错
23/10/07 11:23:40 WARN Shell: Did not find winutils.exe: {} java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir are unset.
-
-
原因分析
- Spark程序运行时找不到winutils.exe程序或依赖
-
解决方法
-
下载winutils.exe程序
-
在任意无中文路径位置新建bin目录,例如
目录路径位置随意,但一定不要有中文目录
D:/shujia/bigdata/hadoop3/bin
-
将winutils.exe程序放入上述bin目录中
-
在系统环境变量中增加一项HADOOP_HOME配置
-
将
D:/shujia/bigdata/hadoop3/
目录作为HADOOP_HOME的值注意不要将bin目录包含在其中
-
重启IDEA
- 重新运行程序,检查错误是否消失
-
Standalone模式
-
1、上传解压
tar -zxvf spark-3.1.3-bin-without-hadoop.tgz -C /usr/local/soft mv spark-3.1.3-bin-without-hadoop spark-3.1.3
-
2、修改配置文件
# 重命名文件 cp spark-env.sh.template spark-env.sh cp workers.template workers
增加配置:
vim spark-env.sh
master相当于RM worker相当于NM
export SPARK_MASTER_HOST=master export SPARK_MASTER_PORT=7077 export SPARK_WORKER_CORES=1 export SPARK_WORKER_MEMORY=2g export JAVA_HOME=/usr/local/soft/jdk1.8.0_171 export SPARK_DIST_CLASSPATH=$(/usr/local/soft/hadoop-3.1.1/bin/hadoop classpath)
增加从节点配置:
vim workers
以node1、node2作为从节点
node1 node2
-
3、复制到其它节点
cd /usr/local/soft/ scp -r spark-3.1.3 node1:`pwd` scp -r spark-3.1.3 node2:`pwd`
-
4、配置环境变量
-
5、在主节点执行启动命令
注意:start-all.sh 与Hadoop的sbin目录中的启动命令有冲突
cd /usr/local/soft/spark-3.1.3/ ./sbin/start-all.sh
-
6、访问Spark Web UI
http://master:8080/
-
7、测试及使用
切换目录:
cd /usr/local/soft/spark-3.1.3/examples/jars
standalone client模式 :日志在本地输出,一般用于上线前测试
-
提交自带的SparkPi任务
spark-submit --class org.apache.spark.examples.SparkPi --master spark://master:7077 --executor-memory 512m --total-executor-cores 1 spark-examples_2.12-3.1.3.jar 100
standalone cluster模式:上线使用,不会在本地打印日志
-
提交自带的SparkPi任务
spark-submit --class org.apache.spark.examples.SparkPi --master spark://master:7077 --executor-memory 512M --total-executor-cores 1 --deploy-mode cluster spark-examples_2.12-3.1.3.jar 100
-
-
8、其他运行方式
-
spark-shell spark 提供的一个交互式的命令行,可以直接写代码
spark-shell --master spark://master:7077
-
On Yarn模式
在公司一般不适用standalone模式
因为公司一般已经有yarn 不需要搞两个资源管理框架
Spark整合yarn只需要在一个节点整合, 可以删除node1 和node2中所有的Spark 文件
-
1、停止Spark Standalone模式集群
# 切换目录 cd /usr/local/soft/spark-3.1.3/ # 停止集群 ./sbin/stop-all.sh
-
2、增加hadoop 配置文件地址
vim spark-env.sh # 增加HADOOP_CONF_DIR export HADOOP_CONF_DIR=/usr/local/soft/hadoop-3.1.1/etc/hadoop
-
3、关闭Yarn
stop-yarn.sh
-
4、修改Yarn配置
cd /usr/local/soft/hadoop-3.1.1/etc/hadoop/ vim yarn-site.xml # 加入如下配置 <property> <name>yarn.nodemanager.pmem-check-enabled</name> <value>false</value> </property> <property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property>
-
5、同步到其他节点
scp -r yarn-site.xml node1:`pwd` scp -r yarn-site.xml node2:`pwd`
-
6、启动Yarn
start-yarn.sh
-
7、测试及使用
切换目录:
cd /usr/local/soft/spark-3.1.3/examples/jars
Spark on Yarn Client模式:日志在本地输出,一班用于上线前测试
-
提交自带的SparkPi任务
spark-submit --master yarn --deploy-mode client --class org.apache.spark.examples.SparkPi --executor-memory 512M --num-executors 2 spark-examples_2.12-3.1.3.jar 100
Spark on Yarn Cluster模式:上线使用,不会在本地打印日志
-
提交自带的SparkPi任务
spark-submit --master yarn --deploy-mode cluster --class org.apache.spark.examples.SparkPi --executor-memory 512M --num-executors 2 spark-examples_2.12-3.1.3.jar 100
-
获取yarn程序执行日志 执行成功之后才能获取到
yarn logs -applicationId application_1652086375126_0002
-
-
8、开启Spark On Yarn的WEB UI
修改配置文件:
# 切换目录 cd /usr/local/soft/spark-3.1.3/conf # 去除后缀 cp spark-defaults.conf.template spark-defaults.conf # 修改spark-defaults.conf vim spark-defaults.conf # 加入以下配置 spark.eventLog.enabled true spark.eventLog.dir hdfs://master:9000/user/spark/applicationHistory spark.yarn.historyServer.address master:18080 spark.eventLog.compress true spark.history.fs.logDirectory hdfs://master:9000/user/spark/applicationHistory spark.history.retainedApplications 15
创建HDFS目录用于存储Spark History日志
hdfs dfs -mkdir -p /user/spark/applicationHistory
启动Spark History Server
cd /usr/local/soft/spark-3.1.3/ ./sbin/start-history-server.sh
RDD的五大特性
-
A list of partitions RDD是由一系列的分区组成的,第一个RDD的分区由切片数量决定
-
A function for computing each split Task是作用在每一个分区上的
-
A list of dependencies on other RDDs
-
Optionally, a Partitioner for key-value RDDs
-
Optionally, a list of preferred locations to compute each split on
package com.shujia.spark.core import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object Demo01WordCnt { // 第一个Spark程序:wordCount def main(args: Array[String]): Unit = { // 构建Spark的配置文件 val conf: SparkConf = new SparkConf() // 配置Spark的运行方式 conf.setMaster("local") // 配置Spark的任务名称 conf.setAppName("Demo01WordCnt") // 构建Spark环境 val sc: SparkContext = new SparkContext(conf) /** * 环境构建好后开始写Spark代码 */ // 1、加载数据 /** * RDD:弹性分布式数据集 * 可以把它当成Scala中的集合使用 * 实际上RDD是Spark中统一的编程模型 * RDD中是不存储数据的 */ /** * RDD的五大特性: * 1、RDD是由一系列分区组成的,第一个RDD的分区数由切片的数量决定的 * 2、Task是作用在每一个分区上的 */ val lineRDD: RDD[String] = sc.textFile("spark/data/words/*") println(lineRDD.getNumPartitions) val wordsRDD: RDD[String] = lineRDD.flatMap(_.split(",")) val grpRDD: RDD[(String, Iterable[String])] = wordsRDD.groupBy(word => word) println(grpRDD.getNumPartitions) val wordCntRDD: RDD[String] = grpRDD.map(kv => { println("进入map方法") s"${kv._1},${kv._2.size}" }) println(wordCntRDD.getNumPartitions) wordCntRDD.foreach(println) // wordCntRDD.saveAsTextFile("spark/data/wcnt/") } }
-