目录
一、什么是Spark
二、主要角色
1、Driver(驱动器)
2、Executor(执行器)
3、Local模式(单个服务器)
4、基本操作
5、Standalone模式(Master+Slave集群模式)
6、Yarn模式(重点)
7、Mesos模式
三、案例
1、wordcount案例
一、什么是Spark
spark是一种基于内存的快速、通用、可扩展的大数据分析引擎。
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 设计为可以高效地在一个计算节点到数千个计算节点之间伸缩计 算。为了实现这样的要求,同时获得最大灵活性,Spark支持在各种集群管理器(Cluster Manager)上运行,包括Hadoop YARN、Apache Mesos,以及Spark自带的一个简易调度 器,叫作独立调度器。
Spark和MapReduce区别:
都是分布式计算框架,Spark基于内存,MR基于HDFS。Spark处理数据的能力一般是MR的十倍以上,Spark中除了基于内存计算外,还有DAG有向无环图来切分任务的执行先后顺序。(spark比MR快的原因)
二、主要角色
1、Driver(驱动器)
Spark的驱动器是执行开发程序中的main方法的进程。它负责开发人员编写的用来创建SparkContext、创建RDD,以及进行RDD的转化操作和行动操作代码的执行。如果你是用spark shell,那么当你启动Spark shell的时候,系统后台自启了一个Spark驱动器程序,就是在Spark shell中预加载的一个叫作 sc的SparkContext对象。如果驱动器程序终止,那么Spark应用也就结束了。主要负责:
1)把用户程序转为作业(JOB)
2)跟踪Executor的运行状况
3)为执行器节点调度任务
4)UI展示应用运行状况
2、Executor(执行器)
Spark Executor是一个工作进程,负责在 Spark 作业中运行任务,任务间相互独立。Spark 应用启动时,Executor节点被同时启动,并且始终伴随着整个 Spark 应用的生命周期而存在。如果有Executor节点发生了故障或崩溃,Spark 应用也可以继续执行,会将出错节点上的任务调度到其他Executor节点上继续运行。主要负责:
1)负责运行组成 Spark 应用的任务,并将结果返回给驱动器进程;
2)通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。
3、Local模式(单个服务器)
多用于本地测试,如在eclipse,idea中写程序测试等。
Local模式就是运行在一台计算机上的模式,通常就是用于本机上练手和测试。它可以通过以下集中方式设置Master:
1)local:所有计算都运行在一个线程当中,没有任何的并行计算,通常我们在本机执行一些代码测试或者练手,都是i这种模式。
2)local[K]:指定使用几个线程来运行计算,比如local[4] 就是运行4个Worker线程,通常我们cpu有几个core就设定计个线程,也可以使用local[*]直接设定最大线程数
4、基本操作
(1)基本语法
bin/spark-submit \
--class <main-class>
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key>=<value> \
... # other options
<application-jar> \
[application-arguments]
(2)参数说明:
--master 指定Master的地址,默认为Local
--class: 你的应用的启动类 (如 org.apache.spark.examples.SparkPi)
--deploy-mode: 是否发布你的驱动到worker节点(cluster) 或者作为一个本地客户端 (client) (default: client)*
--conf: 任意的Spark配置属性, 格式key=value. 如果值包含空格,可以加引号“key=value”
application-jar: jar包,包含依赖. 这个URL在集群中全局可见。 比如hdfs:// 共享存储系统, 如果是 file:// path, 那么所有的节点的path都包含同样的jar
application-arguments: 传给main()方法的参数
--executor-memory 1G 指定每个executor可用内存为1G
--total-executor-cores 2 指定每个executor使用的cup核数为2个
3、交互shell执行wordcount案例
(1)打开shell
bin/spark-shell --master local[*]
(2)执行指令 可以登录hdp-1:4040查看程序运行
#输出在控制台 /spark/hi.txt是hdfs地址还是本地/yarn,根据部署方式
scala>sc.textFile("/spark/hi.txt").flatMap(_.split(",")).map((_,1)).reduceByKey(_+_).collect
#输出到文件
sc.textFile("/spark/hi.txt").flatMap(_.split(",")).map((_,1)).reduceByKey(_+_).saveAsTextFile("/spark/out")
textFile("input"):读取本地文件input文件夹数据;
flatMap(_.split(" ")):压平操作,按照空格分割符将一行数据映射成一个个单词;
map((_,1)):对每一个元素操作,将单词映射为元组;
reduceByKey(_+_):按照key将值进行聚合,相加;
collect:将数据收集到Driver端展示。
过程:
登陆 http://hdp-1:4040/ 查看程序状态
5、Standalone模式(Master+Slave集群模式)
Standalone是Spark自带的一个资源调度框架,它支持完全分布式。
./spark-shell --master spark://hdp-2:7077 --executor-memory 500m --total-executor-cores 1
6、Yarn模式(重点)
Hadoop生态圈里面的一个资源调度框架,Spark也是可以基于Yarn来计算的。
Spark客户端直接连接Yarn,不需要额外构建Spark集群。有yarn-client和yarn-cluster两种模式,主要区别在于:Driver程序的运行节点。
yarn-client:Driver程序运行在客户端,适用于交互、调试,希望立即看到app的输出
yarn-cluster:Driver程序运行在由RM(ResourceManager)启动的AP(APPMaster)适用于生产环境。
安装使用
1)修改hadoop配置文件yarn-site.xml,添加如下内容:
<!--是否启动一个线程检查每个任务正使用的物理内存量,如果任务超出分配值,则直接将其杀掉,默认是true -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<!--是否启动一个线程检查每个任务正使用的虚拟内存量,如果任务超出分配值,则直接将其杀掉,默认是true -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
修改spark-env.sh,添加如下配置:
YARN_CONF_DIR=/opt/module/hadoop-2.7.2/etc/hadoop
提交任务到Yarn执行
[xin@hdp-1 spark]$ bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
./examples/jars/spark-examples_2.11-2.1.1.jar \
100
提交到yarn集群上运行
spark-shell --master yarn --deploy-mode client
scala> val array = Array(1,2,3,4,5)
array: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val rdd = sc.makeRDD(array)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at makeRDD at <console>:26
scala> rdd.count
res0: Long = 5
7、Mesos模式
资源调度框架,Spark客户端直接连接Mesos;不需要额外构建Spark集群。国内应用比较少,更多的是运用yarn调度
几种模式对比:
模式 | Spark安装机器数 | 需启动的进程 | 所属者 |
Local | 1 | 无 | Spark |
Standalone | 3 | Master及Worker | Spark |
Yarn | 1 | Yarn及HDFS | Hadoop |
三、案例
1、wordcount案例
详细依赖
<?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>com.bjsxt.spark</groupId>
<artifactId>MySpark</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 配置以下可以解决 在jdk1.8环境下打包时报错 “-source 1.5 中不支持 lambda 表达式” -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spark-core -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.3.1</version>
</dependency>
<!-- SparkSQL -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.3.1</version>
</dependency>
<!-- SparkSQL ON Hive-->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.11</artifactId>
<version>2.3.1</version>
</dependency>
<!--mysql依赖的jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--SparkStreaming-->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.3.1</version>
<!--<scope>provided</scope>-->
</dependency>
<!-- SparkStreaming + Kafka -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 向kafka 生产数据需要包 -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.0.0</version>
</dependency>
<!--连接 Redis 需要的包-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.1</version>
</dependency>
<!-- Scala 包-->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.11.7</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>2.11.7</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
<version>2.11.7</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 在maven项目中既有java又有scala代码时配置 maven-scala-plugin 插件打包时可以将两类代码一起打包 -->
<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>
<!-- maven 打jar包需要插件 -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<!-- 设置false后是去掉 MySpark-1.0-SNAPSHOT-jar-with-dependencies.jar 后的 “-jar-with-dependencies” -->
<!--<appendAssemblyId>false</appendAssemblyId>-->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.bjsxt.scalaspark.sql.windows.OverFunctionOnHive</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 以上assembly可以将依赖的包打入到一个jar包中,下面这种方式是使用maven原生的方式打jar包,不将依赖的包打入到最终的jar包中 -->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-jar-plugin</artifactId>-->
<!--<version>2.4</version>-->
<!--<configuration>-->
<!--<archive>-->
<!--<manifest>-->
<!--<addClasspath>true</addClasspath>-->
<!--<!– 指定当前主类运行时找依赖的jar包时 所有依赖的jar包存放路径的前缀 –>-->
<!--<classpathPrefix>/alljars/lib</classpathPrefix>-->
<!--<mainClass>com.bjsxt.javaspark.sql.CreateDataSetFromHive</mainClass>-->
<!--</manifest>-->
<!--</archive>-->
<!--</configuration>-->
<!--</plugin>-->
<!-- 拷贝依赖的jar包到lib目录 -->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-dependency-plugin</artifactId>-->
<!--<executions>-->
<!--<execution>-->
<!--<id>copy</id>-->
<!--<phase>package</phase>-->
<!--<goals>-->
<!--<goal>copy-dependencies</goal>-->
<!--</goals>-->
<!--<configuration>-->
<!--<outputDirectory>-->
<!--<!– 将依赖的jar 包复制到target/lib下–>-->
<!--${project.build.directory}/lib-->
<!--</outputDirectory>-->
<!--</configuration>-->
<!--</execution>-->
<!--</executions>-->
<!--</plugin>-->
</plugins>
</build>
</project>
scala代码
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object ScalaWordCount {
def main(args: Array[String]): Unit = {
//创建spark配置,设置应用程序名字
//val conf = new SparkConf().setAppName("ScalaWordCount")
val conf = new SparkConf().setAppName("ScalaWordCount").setMaster("local[4]")
//创建spark执行的入口
val sc = new SparkContext(conf)
//指定以后从哪里读取数据创建RDD(弹性分布式数据集)并执行相应的transformation和action
//sc.textFile(args(0)).flatMap(_.split(" ")).map((_, 1)).reduceByKey(_+_).sortBy(_._2, false).saveAsTextFile(args(1))
val lines: RDD[String] = sc.textFile(args(0))
//切分压平 _代表一行内容
val words: RDD[String] = lines.flatMap(_.split(","))
//将单词和一组合,形成一个元组
val wordAndOne: RDD[(String, Int)] = words.map((_, 1))
//按key进行聚合 _+_是1+1,2+1,3+1 .....
val reduced: RDD[(String, Int)] = wordAndOne.reduceByKey(_ + _)
// wordAndOne.reduceByKey((x:Int,y:Int)=>x+y)
//排序 _._2 根据第二个数据排序 <hello,3>根据3排序,false表示降序,ascending=false
val sorted: RDD[(String, Int)] = reduced.sortBy(_._2, false)
//将结果保存到HDFS中
sorted.saveAsTextFile(args(1))
//释放资源
sc.stop()
}
打成jar包提交到集群运行
spark/bin/spark-submit --master spark://hdp-1:7077 --class com.zpark.wc.ScalaWordCount /root/apps/original-sparkwctwo-1.0-SNAPSHOT.jar hdfs://hdp-1:9000/spark/hi.txt hdfs://hdp-1:9000/spark/out
#yarn方式
bin/spark-submit \
--class com.zpark.wc.ScalaWordCount \
--master yarn \
--deploy-mode client \
/root/apps/original-sparkwctwo-1.0-SNAPSHOT.jar hdfs://hdp-1:9000/spark/hi.txt hdfs://hdp-1:9000/spark/out