Spark教程(三)—— 安装与使用

        Spark可以独立安装使用,也可以和Hadoop一起安装使用。本教程中,我们采用和Hadoop一起安装使用,这样,就可以让Spark使用HDFS存取数据。需要说明的是,当安装好Spark以后,里面就自带了scala环境,不需要额外安装scala,因此,“Spark安装”这个部分的教程,假设读者的计算机上,没有安装Scala,也没有安装Java(当然了,如果已经安装Java和Scala,也没有关系,依然可以继续按照本教程进行安装),也就是说,你的计算机目前只有Linux系统,其他的软件和环境都没有安装(没有Java,没有Scala,没有Hadoop,没有Spark),需要从零开始安装所有大数据相关软件。下面,需要你在自己的Linux系统上(笔者采用的Linux系统是Ubuntu16.04),首先安装Java和Hadoop,然后再安装Spark(Spark安装好以后,里面就默认包含了Scala解释器)。由于Ubuntu 16.04已经自带了Python 3.5版本,所以你的系统如果是Ubuntu 16.04,那么就不需要重新安装Python了。本教程也将以python3语法进行教学。
本教程的具体运行环境如下:

  • Ubuntu16.04以上
  • Hadoop 2.7.1以上
  • Java JDK 1.8以上
  • Spark 2.1.0 以上
  • Python 3.4以上

一. 安装Hadoop

        如果你的计算机上已经安装了Hadoop,本步骤可以略过。这里假设没有安装。如果没有安装Hadoop,请访问链接. 注意,在这个Hadoop安装教程中,就包含了Java的安装,所以,按照这个教程,就可以完成JDK和Hadoop这二者的安装. 此外安装Hadoop主要是为了使用HDFS. 下面会就HDFS如何使用做一些说明.

        首先启动HDFS组件

cd /usr/local/hadoop
./sbin/start-dfs.sh

        启动结束后,HDFS开始进入可用状态。如果你在HDFS文件系统中,还没有为当前Linux登录用户创建目录(本教程统一使用用户名hadoop登录Linux系统),请使用下面命令创建:

./bin/hdfs dfs -mkdir -p /user/hadoop

        也就是说,HDFS文件系统为Linux登录用户开辟的默认目录是“/user/用户名”(注意:是user,不是usr),本教程统一使用用户名hadoop登录Linux系统,所以,上面创建了“/user/hadoop”目录,再次强调,这个目录是在HDFS文件系统中,不在本地文件系统中。创建好以后,下面我们使用命令查看一下HDFS文件系统中的目录和文件:

./bin/hdfs dfs -ls .

        上面命令中,最后一个点号“.”,表示要查看Linux当前登录用户hadoop在HDFS文件系统中与hadoop对应的目录下的文件,也就是查看HDFS文件系统中“/user/hadoop/”目录下的文件,所以,下面两条命令是等价的:

./bin/hdfs dfs -ls .
./bin/hdfs dfs -ls /user/hadoop

        如果要查看HDFS文件系统根目录下的内容,需要使用下面命令:

./bin/hdfs dfs -ls /

        下面,我们把本地文件系统中的“/usr/local/spark/mycode/wordcount/word.txt”上传到分布式文件系统HDFS中(放到hadoop用户目录下):

./bin/hdfs dfs -put /usr/local/spark/mycode/wordcount/word.txt .

        然后,用命令查看一下HDFS的hadoop用户目录下是否多了word.txt文件,可以使用下面命令列出hadoop目录下的内容:

./bin/hdfs dfs -ls .

        可以看到,确实多了一个word.txt文件,我们使用cat命令查看一个HDFS中的word.txt文件的内容,命令如下:

./bin/hdfs dfs -cat ./word.txt

        上面命令执行后,就会看到HDFS中word.txt的内容了。

二. 安装Spark

        在Linux系统中打开浏览器,访问Spark官方下载地址, 按照如图下载.

        由于我们已经自己安装了Hadoop,所以,在“Choose a package type”后面需要选择“Pre-build with user-provided Hadoop [can use with most Hadoop distributions]”,然后,点击“Download Spark”后面的“spark-2.1.0-bin-without-hadoop.tgz”下载即可。下载的文件,默认会被浏览器保存在“/home/hadoop/下载”目录下。需要说明的是,Pre-build with user-provided Hadoop: 属于“Hadoop free”版,这样,下载到的Spark,可应用到任意Hadoop 版本。

        Spark部署模式主要有四种:Local模式(单机模式)、Standalone模式(使用Spark自带的简单集群管理器)、YARN模式(使用YARN作为集群管理器)和Mesos模式(使用Mesos作为集群管理器)。

        这里介绍Local模式(单机模式)的 Spark安装。我们选择Spark 2.1.0版本,并且假设当前使用用户名hadoop登录了Linux操作系统。

sudo tar -zxf ~/下载/spark-2.1.0-bin-without-hadoop.tgz -C /usr/local/
cd /usr/local
sudo mv ./spark-2.1.0-bin-without-hadoop/ ./spark
sudo chown -R hadoop:hadoop ./spark          # 此处的 hadoop 为你的用户名

        安装后,还需要修改Spark的配置文件spark-env.sh

cd /usr/local/spark
cp ./conf/spark-env.sh.template ./conf/spark-env.sh

        编辑spark-env.sh文件(vim ./conf/spark-env.sh),在第一行添加以下配置信息:

export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/bin/hadoop classpath)

        有了上面的配置信息以后,Spark就可以把数据存储到Hadoop分布式文件系统HDFS中,也可以从HDFS中读取数据。如果没有配置上面信息,Spark就只能读写本地数据,无法读写HDFS数据。

        然后通过如下命令,修改环境变量.

vim ~/.bashrc

        在.bashrc文件中添加如下内容

export JAVA_HOME=/usr/lib/jvm/default-java
export HADOOP_HOME=/usr/local/hadoop
export SPARK_HOME=/usr/local/spark
export PYTHONPATH=$SPARK_HOME/python:$SPARK_HOME/python/lib/py4j-0.10.4-src.zip:$PYTHONPATH
export PYSPARK_PYTHON=python3
export PATH=$HADOOP_HOME/bin:$SPARK_HOME/bin:$PATH

        PYTHONPATH环境变量主要是为了在Python3中引入pyspark库,PYSPARK_PYTHON变量主要是设置pyspark运行的python版本。
        .bashrc中必须包含JAVA_HOME,HADOOP_HOME,SPARK_HOME,PYTHONPATH,PYSPARK_PYTHON,PATH这些环境变量。如果已经设置了这些变量则不需要重新添加设置。
        接着还需要让该环境变量生效,执行如下代码:

source ~/.bashrc

        配置完成后就可以直接使用,不需要像Hadoop运行启动命令。
        通过运行Spark自带的示例,验证Spark是否安装成功。

cd /usr/local/spark
bin/run-example SparkPi

        执行时会输出非常多的运行信息,输出结果不容易找到,可以通过 grep 命令进行过滤(命令中的 2>&1 可以将所有的信息都输出到 stdout 中,否则由于输出日志的性质,还是会输出到屏幕中):

bin/run-example SparkPi 2>&1 | grep "Pi is"

        这里涉及到Linux Shell中管道的知识,详情可以参考Linux Shell中的管道命令

        过滤后的运行结果如下图示,可以得到π 的 5 位小数近似值:

三. Spark的启动参数以及在pySpark中运行代码

        启动spark, 命令如下:

bin/pyspark

        如果没有设置PYSPARK_PYTHON环境变量,则使用如下命令启动pyspark:

PYSPARK_PYTHON=python3
./bin/pyspark

        pyspark命令及其常用的参数如下:

./bin/pyspark --master <master-url>

        Spark的运行模式取决于传递给SparkContext的Master URL的值。Master URL可以是以下任一种形式:

  • local 使用一个Worker线程本地化运行SPARK(完全不并行)
  • local[*] 使用逻辑CPU个数数量的线程来本地化运行Spark
  • local[K] 使用K个Worker线程本地化运行Spark(理想情况下,K应该根据运行机器的CPU核数设定)
  • spark://HOST:PORT 连接到指定的Spark standalone master。默认端口是7077
  • yarn-client 以客户端模式连接YARN集群。集群的位置可以在HADOOP_CONF_DIR 环境变量中找到
  • yarn-cluster 以集群模式连接YARN集群。集群的位置可以在HADOOP_CONF_DIR 环境变量中找到
  • mesos://HOST:PORT 连接到指定的Mesos集群。默认接口是5050

        需要强调的是,这里我们采用“本地模式”(local)运行Spark,关于如何在集群模式下运行Spark,可以参考后面的“在集群上运行Spark应用程序”。

        在Spark中采用本地模式启动pyspark的命令主要包含以下参数:

  • master:这个参数表示当前的pyspark要连接到哪个master,如果是local[*],就是使用本地模式启动pyspark,其中,中括号内的星号表示需要使用几个CPU核心(core)
  • jars: 这个参数用于把相关的JAR包添加到CLASSPATH中;如果有多个jar包,可以使用逗号分隔符连接它们

        比如,要采用本地模式,在4个CPU核心上运行pyspark:

cd /usr/local/spark
./bin/pyspark --master local[4]

        或者,可以在CLASSPATH中添加code.jar,命令如下:

cd /usr/local/spark
./bin/pyspark --master local[4] --jars code.jar 

        可以执行“pyspark –help”命令,获取完整的选项列表,具体如下:

cd /usr/local/spark
./bin/pyspark --help

        上面是命令使用方法介绍,下面正式使用命令进入pyspark环境,可以通过下面命令启动pyspark环境:

bin/pyspark

        该命令省略了参数,这时,系统默认是“bin/pyspark–master local[*]”,也就是说,是采用本地模式运行,并且使用本地所有的CPU核心。启动pyspark后,就会进入“>>>”命令提示符状态,如下图所示:

        现在,你就可以在里面输入python代码进行调试了。比如,下面在命令提示符后面输入一个表达式“8 * 2 + 5”,然后回车,就会立即得到结果:

8 * 2 + 5

四. 本地文件统计词频

(1) 首先编一些语聊便于统计词频

        进入Linux系统,打开“终端”,进入Shell命令提示符状态,然后,执行如下命令新建目录:

cd /usr/local/spark
mkdir mycode
cd mycode
mkdir wordcount
cd wordcount

        然后,在“/usr/local/spark/mycode/wordcount”目录下新建一个包含了一些语句的文本文件word.txt,命令如下:

vim word.txt

        可以在文本文件中随意输入一些单词,用空格隔开,我们会编写Spark程序对该文件进行单词词频统计。然后,按键盘Esc键退出vim编辑状态,输入“:wq”保存文件并退出vim编辑器。

(2) 借用pyspark进行词频统计

from pyspark.sql import SparkSession
from pyspark import SparkContext, SparkConf
from pyspark.sql.types import Row, StructType, StructField, StringType

# spark加载本地文件
sc = SparkContext('local', 'test')
textFile = sc.textFile("file:///usr/local/spark/mycode/wordcount/word.txt")
wordCount = textFile.flatMap(lambda line: line.split(" ")).map(lambda word: (word,1)).reduceByKey(lambda a, b : a + b)
wordCount.foreach(print)

# 将textFile保存到文件中, 是为了使用saveAsTextFile这个函数
textFile.saveAsTextFile("file:///usr/local/spark/mycode/wordcount/writeback")

        上面代码中,sc.textFile()中的这个textFile是sc的一个方法名称,这个方法用来加载文件数据。这两个textFile不是一个东西,不要混淆。实际上,前面的变量textFile,你完全可以换个变量名称. 这里使用相同名称,就是有意强调二者的区别。
注意,要加载本地文件,必须采用“file:///”开头的这种格式。执行上上面这条命令以后,并不会马上显示结果,因为,Spark采用惰性机制,只有遇到“行动”类型的操作,才会从头到尾执行所有操作。

        上面的saveAsTextFile()括号里面的参数是保存文件的路径,不是文件名。saveAsTextFile()是一个“行动”(Action)类型的操作,所以,马上会执行真正的计算过程,从word.txt中加载数据到变量textFile中,然后,又把textFile中的数据写回到本地文件目录“/usr/local/spark/mycode/wordcount/writeback/”下面,现在让我们切换到Linux Shell命令提示符窗口中,执行下面命令:

cd /usr/local/spark/mycode/wordcount/writeback/
ls

        执行结果类似下面:

part-00000 _SUCCESS

        也就是说,该目录下包含两个文件,我们可以使用cat命令查看一下part-00000文件(注意:part-后面是五个零)

cat part-00000

        显示结果,是和上面word.txt中的内容一样的。

五. HDFS统计词频

from pyspark.sql import SparkSession
from pyspark import SparkContext, SparkConf
from pyspark.sql.types import Row, StructType, StructField, StringType

# spark加载HDFS
sc = sc = SparkContext('local', 'test')
textFile = sc.textFile("hdfs://localhost:9000/user/liuxu/word.txt")
wordCount = textFile.flatMap(lambda line: line.split(" ")).map(lambda word: (word,1)).reduceByKey(lambda a, b : a + b)
wordCount.foreach(print)

        从HDFS中的读取数据 和 从本地文件中读取数据的主要区别在于sc.textFile()里面的文件路径不一致.

六. 词频统计代码注释

        textFile.flatMap(labmda line : line.split(” “)) - 会遍历textFile中的每行文本内容,当遍历到其中一行文本内容时,会把文本内容赋值给变量line,并执行Lamda表达式line : line.split(” “)。line : line.split(” “)是一个Lamda表达式,左边表示输入参数,右边表示函数里面执行的处理逻辑,这里执行line.split(” “),也就是针对line中的一行文本内容,采用空格作为分隔符进行单词切分,从一行文本切分得到很多个单词构成的单词集合。这样,对于textFile中的每行文本,都会使用Lamda表达式得到一个单词集合,最终,多行文本,就得到多个单词集合。textFile.flatMap()操作就把这多个单词集合“拍扁”得到一个大的单词集合。

        map(lambda word : (word, 1)),这个map操作会遍历这个集合中的每个单词,当遍历到其中一个单词时,就把当前这个单词赋值给变量word,并执行Lamda表达式word : (word, 1),这个Lamda表达式的含义是,word作为函数的输入参数,然后,执行函数处理逻辑,这里会执行(word, 1),也就是针对输入的word,构建得到一个tuple,形式为(word,1),key是word,value是1(表示该单词出现1次)

        程序执行到这里,已经得到一个RDD,这个RDD的每个元素是(key,value)形式的tuple。最后,针对这个RDD,执行reduceByKey(labmda a, b : a + b)操作,这个操作会把所有RDD元素按照key进行分组,然后使用给定的函数(这里就是Lamda表达式:a, b : a + b),对具有相同的key的多个value进行reduce操作,返回reduce后的(key,value),比如(“hadoop”,1)和(“hadoop”,1),具有相同的key,进行reduce以后就得到(“hadoop”,2),这样就计算得到了这个单词的词频。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值