Spark基础篇

目录

 

一、什么是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>-->
                            <!--&lt;!&ndash; 指定当前主类运行时找依赖的jar包时 所有依赖的jar包存放路径的前缀 &ndash;&gt;-->
                            <!--<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>-->
                                <!--&lt;!&ndash; 将依赖的jar 包复制到target/lib下&ndash;&gt;-->
                                <!--${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


 

发布了77 篇原创文章 · 获赞 19 · 访问量 4064

猜你喜欢

转载自blog.csdn.net/qq_41861558/article/details/103050302
今日推荐