Spark入门必看

什么是Spark(官网:http://spark.apache.org

在这里插入图片描述
Spark是一种快速、通用、可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPLab,2010年开源,2013年6月成为Apache孵化项目,2014年2月成为Apache顶级项目。目前,Spark生态系统已经发展成为一个包含多个子项目的集合,其中包含SparkSQL、Spark Streaming、GraphX、MLlib等子项目,Spark是基于内存计算的大数据并行计算框架。Spark基于内存计算,提高了在大数据环境下数据处理的实时性,同时保证了高容错性和高可伸缩性,允许用户将Spark部署在大量廉价硬件之上,形成集群。Spark得到了众多大数据公司的支持,这些公司包括Hortonworks、IBM、Intel、Cloudera、MapR、Pivotal、百度、阿里、腾讯、京东、携程、优酷土豆。当前百度的Spark已应用于凤巢、大搜索、直达号、百度大数据等业务;阿里利用GraphX构建了大规模的图计算和图挖掘系统,实现了很多生产系统的推荐算法;腾讯Spark集群达到8000台的规模,是当前已知的世界上最大的Spark集群。
2.2为什么要学Spark
Spark是一个开源的类似于Hadoop MapReduce的通用的并行计算框架,Spark基于map reduce算法实现的分布式计算,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是Spark中的Job中间输出和结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的map reduce的算法。
Spark是MapReduce的替代方案,而且兼容HDFS、Hive,可融入Hadoop的生态系统,以弥补MapReduce的不足。

2.3 Spark特点
2.3.1 快
与Hadoop的MapReduce相比,Spark基于内存的运算要快100倍以上,基于硬盘的运算也要快10倍以上。Spark实现了高效的DAG执行引擎,可以通过基于内存来高效处理数据流。

2.3.2 易用
Spark支持Java、Python和Scala的API,还支持超过80种高级算法,使用户可以快速构建不同的应用。而且Spark支持交互式的Python和Scala的shell,可以非常方便地在这些shell中使用Spark集群来验证解决问题的方法。

2.3.4 通用
Spark提供了统一的解决方案。Spark可以用于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)。这些不同类型的处理都可以在同一个应用中无缝使用。Spark统一的解决方案非常具有吸引力,毕竟任何公司都想用统一的平台去处理遇到的问题,减少开发和维护的人力成本和部署平台的物力成本。
2.3.5 兼容性
Spark可以非常方便地与其他的开源产品进行融合。比如,Spark可以使用Hadoop的YARN和Apache Mesos作为它的资源管理和调度器,器,并且可以处理所有Hadoop支持的数据,包括HDFS、HBase和Cassandra等。这对于已经部署Hadoop集群的用户特别重要,因为不需要做任何数据迁移就可以使用Spark的强大处理能力。Spark也可以不依赖于第三方的资源管理和调度器,它实现了Standalone作为其内置的资源管理和调度框架,这样进一步降低了Spark的使用门槛,使得所有人都可以非常容易地部署和使用Spark。此外,Spark还提供了在EC2上部署Standalone的Spark集群的工具。
在这里插入图片描述
三、 Spark集群安装
3.1 下载spark安装包
下载地址spark官网:http://spark.apache.org/downloads.html
这里我们使用 spark-2.0.2-bin-hadoop2.7版本.
在这里插入图片描述
3.2 规划安装目录
mkdir /opt/bigdata
3.3 上传,解压安装包
tar -zxvf spark-2.0.2-bin-hadoop2.7.tgz
3.4 重命名目录
mv spark-2.0.2-bin-hadoop2.7 spark
3.5 修改配置文件

配置文件目录在 /opt/bigdata/spark/conf
 vi spark-env.sh 修改文件(先把spark-env.sh.template重命名为spark-env.sh)

#配置java环境变量
export JAVA_HOME=/opt/bigdata/jdk1.7.0_67
#指定spark老大Master的IP
export SPARK_MASTER_HOST=hdp-node-01
#指定spark老大Master的端口
export SPARK_MASTER_PORT=7077
 vi slaves 修改文件(先把slaves.template重命名为slaves)
hdp-node-02
hdp-node-03
3.6 拷贝配置到其他主机
通过scp 命令将spark的安装目录拷贝到其他机器上
scp -r /opt/bigdata/spark hdp-node-02:/opt/bigdata
scp -r /opt/bigdata/spark hdp-node-03:/opt/bigdata

3.7 配置spark环境变量
将spark添加到环境变量,添加以下内容到 /etc/profile
export SPARK_HOME=/opt/bigdata/spark
export PATH= P A T H : PATH: PATH:SPARK_HOME/bin
注意最后 source /etc/profile 刷新配置
3.7 启动spark
#在主节点上启动spark
/opt/bigdata/spark/sbin/start-all.sh

3.8 停止spark
#在主节点上停止spark集群
/opt/bigdata/spark/sbin/stop-all.sh

3.9 spark的web界面
正常启动spark集群后,可以通过访问 http://hdp-node-01:8080,查看spark的web界面,查看相关信息。
四、 Spark HA高可用部署
4.1 高可用部署说明
Spark Standalone集群是Master-Slaves架构的集群模式,和大部分的Master-Slaves结构集群一样,存在着Master单点故障的问题。如何解决这个单点故障的问题,Spark提供了两种方案:
(1)基于文件系统的单点恢复(Single-Node Recovery with Local File System)。
主要用于开发或测试环境。当spark提供目录保存spark Application和worker的注册信息,并将他们的恢复状态写入该目录中,这时,一旦Master发生故障,就可以通过重新启动Master进程(sbin/start-master.sh),恢复已运行的spark Application和worker的注册信息。
(2)基于zookeeper的Standby Masters(Standby Masters with ZooKeeper)。
用于生产模式。其基本原理是通过zookeeper来选举一个Master,其他的Master处于Standby状态。将spark集群连接到同一个ZooKeeper实例并启动多个Master,利用zookeeper提供的选举和状态保存功能,可以使一个Master被选举成活着的master,而其他Master处于Standby状态。如果现任Master死去,另一个Master会通过选举产生,并恢复到旧的Master状态,然后恢复调度。整个恢复过程可能要1-2分钟。
4.2 基于zookeeper的Spark HA高可用集群部署
该HA方案使用起来很简单,首先需要搭建一个zookeeper集群,然后启动zooKeeper集群,最后在不同节点上启动Master。具体配置如下:
(1)vim spark-env.sh
注释掉export SPARK_MASTER_HOST=hdp-node-01
(2)在spark-env.sh添加SPARK_DAEMON_JAVA_OPTS,内容如下:
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=hdp-node-01:2181,hdp-node-02:2181,hdp-node-03:2181 -Dspark.deploy.zookeeper.dir=/spark"

参数说明
spark.deploy.recoveryMode:恢复模式(Master重新启动的模式)
有三种:(1)ZooKeeper (2) FileSystem (3)NONE
spark.deploy.zookeeper.url:ZooKeeper的Server地址
spark.deploy.zookeeper.dir:保存集群元数据信息的文件、目录。
包括Worker,Driver和Application。
注意:
在普通模式下启动spark集群,只需要在主机上面执行start-all.sh 就可以了。
在高可用模式下启动spark集群,先需要在任意一台节点上启动start-all.sh命令。然后在另外一台节点上单独启动master。命令start-master.sh

五、 Spark角色介绍
Spark是基于内存计算的大数据并行计算框架。因为其基于内存计算,比Hadoop中MapReduce计算框架具有更高的实时性,同时保证了高效容错性和可伸缩性。从2009年诞生于AMPLab到现在已经成为Apache顶级开源项目,并成功应用于商业集群中,学习Spark就需要了解其架构。
Spark架构图如下:
在这里插入图片描述

Spark架构使用了分布式计算中master-slave模型,master是集群中含有master进程的节点,slave是集群中含有worker进程的节点。
 Driver Program :运⾏main函数并且新建SparkContext的程序。
 Application:基于Spark的应用程序,包含了driver程序和集群上的executor。
 Cluster Manager:指的是在集群上获取资源的外部服务。目前有三种类型
(1)Standalone: spark原生的资源管理,由Master负责资源的分配
(2)Apache Mesos:与hadoop MR兼容性良好的一种资源调度框架
(3)Hadoop Yarn: 主要是指Yarn中的ResourceManager
 Worker Node: 集群中任何可以运行Application代码的节点,在Standalone模式中指的是通过slaves文件配置的Worker节点,在Spark on Yarn模式下就是NodeManager节点
 Executor:是在一个worker node上为某应⽤启动的⼀个进程,该进程负责运⾏行任务,并且负责将数据存在内存或者磁盘上。每个应⽤都有各自独立的executor。
 Task :被送到某个executor上的工作单元。

六、 初识Spark程序
5.1 执行第一个spark程序
普通模式提交任务:
bin/spark-submit
–class org.apache.spark.examples.SparkPi
–master spark://hdp-node-01:7077
–executor-memory 1G
–total-executor-cores 2
examples/jars/spark-examples_2.11-2.0.2.jar
10

该算法是利用蒙特·卡罗算法求圆周率PI,通过计算机模拟大量的随机数,最终会计算出比较精确的π。
在这里插入图片描述

高可用模式提交任务:
在高可用模式下,因为涉及到多个Master,所以对于应用程序的提交就有了一点变化,因为应用程序需要知道当前的Master的IP地址和端口。这种HA方案处理这种情况很简单,只需要在SparkContext指向一个Master列表就可以了,
如spark://host1:port1,host2:port2,host3:port3,应用程序会轮询列表,找到活着的Master。
bin/spark-submit
–class org.apache.spark.examples.SparkPi
–master spark://hdp-node-01:7077,hdp-node-02:7077,hdp-node-03:7077
–executor-memory 1G
–total-executor-cores 2
examples/jars/spark-examples_2.11-2.0.2.jar
10

5.2 启动Spark-Shell
spark-shell是Spark自带的交互式Shell程序,方便用户进行交互式编程,用户可以在该命令行下用scala编写spark程序。
5.2.1 运行spark-shell --master local[N] 读取本地文件
单机模式:通过本地N个线程跑任务,只运行一个SparkSubmit进程。

(1)需求
读取本地文件,实现文件内的单词计数。本地文件words.txt 内容如下:
hello me
hello you
hello her

(2)运行spark-shell --master local[2]

在这里插入图片描述
观察启动的进程:
在这里插入图片描述

(3)编写scala代码
sc.textFile(“file:///root///words.txt”).flatMap(.split(" ")).map((,1)).reduceByKey(+).collect
代码说明:
sc:Spark-Shell中已经默认将SparkContext类初始化为对象sc。用户代码如果需要用到,则直接应用sc即可。
textFile:读取数据文件
flatMap:对文件中的每一行数据进行压平切分,这里按照空格分隔。
map:对出现的每一个单词记为1(word,1)
reduceByKey:对相同的单词出现的次数进行累加
collect:触发任务执行,收集结果数据。
(4)观察结果:
在这里插入图片描述

5.2.2 运行spark-shell --master local[N] 读取HDFS上数据
(1)、整合spark和HDFS,修改配置文件
在spark-env.sh ,添加HADOOP_CONF_DIR配置,指明了hadoop的配置文件后,默认它就是使用的hdfs上的文件在这里插入图片描述
export HADOOP_CONF_DIR=/opt/bigdata/hadoop-2.6.4/etc/hadoop
在这里插入图片描述
(2)、再启动启动hdfs,然后重启spark集群
(3)、向hdfs上传一个文件到hdfs://hdp-node-01:9000/words.txt

(4)、在spark shell中用scala语言编写spark程序
sc.textFile("/words.txt").flatMap(.split(" ")).map((,1)).reduceByKey(+).collect

5.2.3 运行spark-shell 指定具体的master地址
(1)需求:
spark-shell运行时指定具体的master地址,读取HDFS上的数据,做单词计数,然后将结果保存在HDFS上。

(2)执行启动命令:
spark-shell
–master spark://hdp-node-01:7077
–executor-memory 1g
–total-executor-cores 2
在这里插入图片描述

参数说明:
–master spark://hdp-node-01:7077 指定Master的地址
–executor-memory 1g 指定每个worker可用内存为1g
–total-executor-cores 2 指定整个集群使用的cup核数为2个

注意:
如果启动spark shell时没有指定master地址,但是也可以正常启动spark shell和执行spark shell中的程序,其实是启动了spark的local模式,该模式仅在本机启动一个进程,没有与集群建立联系。

(2)编写scala代码
sc.textFile("/words.txt").flatMap(.split(" ")).map((,1)).reduceByKey(+).saveAsTextFile("/wc")

saveAsTextFile:保存结果数据到文件中

(3)查看hdfs上结果

在这里插入图片描述
5.3在IDEA中编写WordCount程序
spark-shell仅在测试和验证我们的程序时使用的较多,在生产环境中,通常会在IDEA中编写程序,然后打成jar包,最后提交到集群。最常用的是创建一个Maven项目,利用Maven来管理jar包的依赖。

(1).创建一个项目

在这里插入图片描述

(2).选择Maven项目,然后点击next
在这里插入图片描述

(3).填写maven的GAV,然后点击next
在这里插入图片描述

(4)填写项目名称,然后点击finish
在这里插入图片描述

(5).创建好maven项目后,点击Enable Auto-Import
在这里插入图片描述

(6)配置Maven的pom.xml

<scala.version>2.11.8</scala.version>
<hadoop.version>2.7.4</hadoop.version>
<spark.version>2.0.2</spark.version>



org.scala-lang
scala-library
s c a l a . v e r s i o n &lt; / v e r s i o n &gt; &lt; / d e p e n d e n c y &gt; &lt; d e p e n d e n c y &gt; &lt; g r o u p I d &gt; o r g . a p a c h e . s p a r k &lt; / g r o u p I d &gt; &lt; a r t i f a c t I d &gt; s p a r k − c o r e 2 . 11 &lt; / a r t i f a c t I d &gt; &lt; v e r s i o n &gt; {scala.version}&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;org.apache.spark&lt;/groupId&gt; &lt;artifactId&gt;spark-core_2.11&lt;/artifactId&gt; &lt;version&gt; scala.version</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>sparkcore2.11</artifactId><version>{spark.version}


org.apache.hadoop
hadoop-client
h a d o o p . v e r s i o n &lt; / v e r s i o n &gt; &lt; / d e p e n d e n c y &gt; &lt; / d e p e n d e n c i e s &gt; &lt; b u i l d &gt; &lt; s o u r c e D i r e c t o r y &gt; s r c / m a i n / s c a l a &lt; / s o u r c e D i r e c t o r y &gt; &lt; t e s t S o u r c e D i r e c t o r y &gt; s r c / t e s t / s c a l a &lt; / t e s t S o u r c e D i r e c t o r y &gt; &lt; p l u g i n s &gt; &lt; p l u g i n &gt; &lt; g r o u p I d &gt; n e t . a l c h i m 31. m a v e n &lt; / g r o u p I d &gt; &lt; a r t i f a c t I d &gt; s c a l a − m a v e n − p l u g i n &lt; / a r t i f a c t I d &gt; &lt; v e r s i o n &gt; 3.2.0 &lt; / v e r s i o n &gt; &lt; e x e c u t i o n s &gt; &lt; e x e c u t i o n &gt; &lt; g o a l s &gt; &lt; g o a l &gt; c o m p i l e &lt; / g o a l &gt; &lt; g o a l &gt; t e s t C o m p i l e &lt; / g o a l &gt; &lt; / g o a l s &gt; &lt; c o n f i g u r a t i o n &gt; &lt; a r g s &gt; &lt; a r g &gt; − d e p e n d e n c y f i l e &lt; / a r g &gt; &lt; a r g &gt; {hadoop.version}&lt;/version&gt; &lt;/dependency&gt; &lt;/dependencies&gt; &lt;build&gt; &lt;sourceDirectory&gt;src/main/scala&lt;/sourceDirectory&gt; &lt;testSourceDirectory&gt;src/test/scala&lt;/testSourceDirectory&gt; &lt;plugins&gt; &lt;plugin&gt; &lt;groupId&gt;net.alchim31.maven&lt;/groupId&gt; &lt;artifactId&gt;scala-maven-plugin&lt;/artifactId&gt; &lt;version&gt;3.2.0&lt;/version&gt; &lt;executions&gt; &lt;execution&gt; &lt;goals&gt; &lt;goal&gt;compile&lt;/goal&gt; &lt;goal&gt;testCompile&lt;/goal&gt; &lt;/goals&gt; &lt;configuration&gt; &lt;args&gt; &lt;arg&gt;-dependencyfile&lt;/arg&gt; &lt;arg&gt; hadoop.version</version></dependency></dependencies><build><sourceDirectory>src/main/scala</sourceDirectory><testSourceDirectory>src/test/scala</testSourceDirectory><plugins><plugin><groupId>net.alchim31.maven</groupId><artifactId>scalamavenplugin</artifactId><version>3.2.0</version><executions><execution><goals><goal>compile</goal><goal>testCompile</goal></goals><configuration><args><arg>dependencyfile</arg><arg>{project.build.directory}/.scala_dependencies






org.apache.maven.plugins
maven-shade-plugin
2.3


package

shade




:

META-INF/.SF
META-INF/.DSA
META-INF/*.RSA













如果出现错误可能是因为版本不兼容问题把pom文件的内容去掉导入一个jar包就可以了

在这里插入图片描述
(7)添加src/main/scala和src/test/scala,与pom.xml中的配置保持一致

在这里插入图片描述

(8)新建一个scala class,类型为Object

在这里插入图片描述
(9).编写spark程序
package cn.test.spark

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

object WordCount {
def main(args: Array[String]): Unit = {
//设置spark的配置文件信息
val sparkConf: SparkConf = new SparkConf().setAppName(“WordCount”)
//构建sparkcontext上下文对象,它是程序的入口,所有计算的源头
val sc: SparkContext = new SparkContext(sparkConf)
//读取文件
val file: RDD[String] = sc.textFile(args(0))

//对文件中每一行单词进行压平切分
val words: RDD[String] = file.flatMap(_.split(" "))
//对每一个单词计数为1 转化为(单词,1)
val wordAndOne: RDD[(String, Int)] = words.map(x=>(x,1))
//相同的单词进行汇总 前一个下划线表示累加数据,后一个下划线表示新数据
val result: RDD[(String, Int)] = wordAndOne.reduceByKey(_+_)
//保存数据到HDFS
result.saveAsTextFile(args(1))
sc.stop()

}
}

(10).使用Maven打包:
点击idea右侧的Maven Project选项
在这里插入图片描述

点击Lifecycle,选择package,然后点击Run Maven Build
在这里插入图片描述

(11).选择编译成功的jar包,并将该jar上传到Spark集群中的某个节点上
在这里插入图片描述

(12).首先启动hdfs和Spark集群
启动hdfs
/opt/bigdata/hadoop-2.6.4/sbin/start-dfs.sh

启动spark
/opt/bigdata/spark/sbin/start-all.sh

(13).使用spark-submit命令提交Spark应用(注意参数的顺序)
spark-submit
–class cn.test.spark.WordCount
–master spark://hdp-node-01:7077
–executor-memory 1g
–total-executor-cores 2
/root/spark-1.0-SNAPSHOT.jar
/words.txt
/spark_out

这里通过spark-submit提交任务到集群上。用的是spark的Standalone模式
Standalone模式是Spark内部默认实现的一种集群管理模式,这种模式是通过集群中的Master来统一管理资源。

  1. 查看Spark的web管理界面
    地址: 192.168.200.160:8080
    在这里插入图片描述
  2. 查看HDFS上的结果文件
    在这里插入图片描述
    hdfs dfs -cat /spark_out/part*
    (hello,3)
    (me,1)
    (you,1)
    (her,1)

5.4 使用java语言编写spark wordcount程序
package cn.bw;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;
import java.util.Arrays;

/**

  • java代码实现spark的WordCount
    */
    public class WordCountJava {
    public static void main(String[] args) {
    //todo:1、构建sparkconf,设置配置信息
    SparkConf sparkConf = new SparkConf().setAppName(“WordCount_Java”).setMaster(“local[2]”);
    //todo:2、构建java版的sparkContext
    JavaSparkContext sc = new JavaSparkContext(sparkConf);
    //todo:3、读取数据文件
    JavaRDD dataRDD = sc.textFile(“d:/data/words1.txt”);
    //todo:4、对每一行单词进行切分
    JavaRDD wordsRDD = dataRDD.flatMap(new FlatMapFunction<String, String>() {
    @Override
    public Iterator call(String s) throws Exception {
    String[] words = s.split(" ");
    return Arrays.asList(words).iterator();
    }
    });
    //todo:5、给每个单词计为 1
    // Spark为包含键值对类型的RDD提供了一些专有的操作。这些RDD被称为PairRDD。
    // mapToPair函数会对一个RDD中的每个元素调用f函数,其中原来RDD中的每一个元素都是T类型的,
    // 调用f函数后会进行一定的操作把每个元素都转换成一个<K2,V2>类型的对象,其中Tuple2为多元组
    JavaPairRDD<String, Integer> wordAndOnePairRDD = wordsRDD.mapToPair(new PairFunction<String, String, Integer>() {
    @Override
    public Tuple2<String, Integer> call(String word) throws Exception {
    return new Tuple2<String,Integer>(word, 1);
    }
    });

     //todo:6、相同单词出现的次数累加
     JavaPairRDD<String, Integer> resultJavaPairRDD = wordAndOnePairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
         @Override
         public Integer call(Integer v1, Integer v2) throws Exception {
             return v1 + v2;
         }
     });
    
     //todo:7、反转顺序
     JavaPairRDD<Integer, String> reverseJavaPairRDD = resultJavaPairRDD.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
         @Override
         public Tuple2<Integer, String> call(Tuple2<String, Integer> tuple) throws Exception {
             return new Tuple2<Integer, String>(tuple._2, tuple._1);
         }
     });
    
     //todo:8、把每个单词出现的次数作为key,进行排序,并且在通过mapToPair进行反转顺序后输出
     JavaPairRDD<String, Integer> sortJavaPairRDD = reverseJavaPairRDD.sortByKey(false).mapToPair(new PairFunction<Tuple2<Integer, String>, String, Integer>() {
         @Override
         public Tuple2<String, Integer> call(Tuple2<Integer, String> tuple) throws Exception {
    
             return  new Tuple2<String, Integer>(tuple._2,tuple._1);
             //或者使用tuple.swap() 实现位置互换,生成新的tuple;
         }
     });
    
     //todo:执行输出
     System.out.println(sortJavaPairRDD.collect());
    
     //todo:关闭sparkcontext
     sc.stop();
    

    }
    }

如有错误请指正谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值