Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。它的特点是多个任务之间数据通信不需要借助硬盘而是通过内存,大大提高了程序的执行效率。
- Spark中间计算结果直接放到内存中,带来了更高的迭代运行效率。
- Spark基于DAG(Directed Acyclic Graph)的任务调度执行机制,要优于MapReduce的迭代执行机制。
下面详细介绍了Spark v2.4.3 最新版详细安装过程以及Spark Shell 命令行操作演示。
一、下载最新版Spark 安装文件
下载URL:
https://spark.apache.org/downloads.html
因为我们已经自己安装了Hadoop,这里选择Pre-build with user-provided Apache Hadoop,也就是使用自己已经安装的Hadoop。
Spark可以独立安装使用,也可以和Hadoop一起安装使用。这样,我们采用和Hadoop一起安装使用,这样就可以让Spark使用HDFS存取数据。需要说明的是,当安装好Spark以后,里面就自带了scala环境,不需要额外安装scala。
从spark官网下载超级慢,可以从国内镜像站点下载:
https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-2.4.3/
执行如下下载命令:
wget https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-2.4.3/spark-2.4.3-bin-without-hadoop.tgz
Spark Maven 依赖,之后开发Java 应用时会需要,可以先保存一下。
groupId: org.apache.spark
artifactId: spark-core_2.11
version: 2.4.3
解压缩
tar -zxf spark-2.4.3-bin-without-hadoop.tgz -C /usr/local
更改目录为简短的spark目录
mv ./spark-2.4.3-bin-without-hadoop/ ./spark
二、配置相关文件
Spark 部署模式有多种,这里演示Local模式(单机模式)的Spark 安装。Spark 版本选择当前最新版本v2.4.3。
进入spark 目录,复制 ./conf/spark-env.sh.template 文件为 ./conf/spark-env.sh,如下所示。
cp ./conf/spark-env.sh.template ./conf/spark-env.sh
vim ./conf/spark-env.sh,在该文件的尾部,添加以下配置项。
export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/hadoop-3.1.2/bin/hadoop classpath)
有了上面的配置信息之后,Spark 就可以把数据存储到 Hadoop 分布式文件系统HDFS中,也可以从 HDFS 中读取数据。
如果没有上述配置信息,Spark 就只能读写本地数据,无法读写HDFS 中的数据。
三、验证Spark 是否安装成功
通过运行Spark 自带的示例,可以验证Spark 是否安装成功。
bin/run-example SparkPi
执行上述命令,会输出大量信息,难以找到最终的输出结果。
可以通过 grep 命令进行过滤,如下所示,获取最终的执行结果。
bin/run-example SparkPi 2>&1 | grep "Pi is roughly"
此时,表示Spark 已经安装成功了。
四、启动Spark Shell
Spark Shell 提供了简单的方式来学习 Spark API,以实时、交互的方式来分析数据。
执行 /bin/spark-shell,进入scala> 命令提示符状态。
现在就可以输入 Scala 代码进行调试了。
如下,在Scala 命令提示符后面,输入表达式 6*6+88,然后就会得到输出结果了。
Spark的主要操作对象是RDD,RDD可以通过多种方式灵活创建。
在Spark 应用中,必须创建一个SparkContext对象,该对象是Spark 应用程序的入口,负责创建RDD、启动任务等等。
在启动Spark Shell后,SparkContext 对象会被自动创建,可以通过变量 sc 进行访问。
读取本地文件rickie.txt作为数据源,新建一个RDD,并显示第一行的内容。
val textFile = sc.textFile("file:///root/rickie.txt")
textFile.first()
查看rickie.txt 文件内容,验证上述代码输出结果符合预期。
collect() 以数组的形式返回数据集中的所有元素;
take(n) 以数组的形式,返回数据集中的前 n 个元素;
启动Hadoop,读取HDFS文件
如果Spark 不使用HDFS,就可以不用启动Hadoop,也可以正常使用Spark。
如果在使用Spark的过程中,需要用到HDFS,就需要先启动Hadoop。
先启动Hadoop。
[root@centos-103 hadoop-3.1.2]# sbin/start-dfs.sh
查看HDFS中的目录(input、output),以及input目录中的文件。
在Spark Shell 窗口中,编写如下代码从HDFS 中加载 rickie.txt文件,并显示第一行的内容。
val textFile=sc.textFile("hdfs://localhost:9000/user/root/input/rickie.txt")
textFile.first()
其中读取HDFS中的文件时,hdfs://localhost:9000/user/root 路径可以省略,代码如下所示。
val textFile=sc.textFile("input/rickie.txt")
编写词频统计程序
textFile包含多行文本内容,flatMap() 遍历每一行文本赋值给遍历line,然后执行 line.split(" "),采用空格作为分隔符进行单词切分,得到多个单词构成的单词集合。
textFile.flatMap() 操作就是把这多个单词集合flat(拍扁)得到一个大的单词集合。
然后针对大的单词集合,执行map() 操作,遍历这个集合中的每个单词,把当前单词赋值给遍历word,并执行Lamda表达式 word =>(word, 1)操作,也就是针对输入的word构建得到一个映射(word, 1)。
这个映射中包含了很多个map - (key, value),最后针对一个map,执行 reduceByKey((a, b)=> a+b) 操作,这个操作会把映射中的所有 (key, value)按照 key 的多个 value进行聚合操作,返回聚合后的 (key, value)。比如("China