本篇博客将介绍如何快速的上手使用spark,关于spark与hadoop安装相关的内容我这里不多说了,对应的资料与博客很多。
在Spark2.0以前,Spark的主要编程接口是RDD(弹性分布式数据集)。在2.0以后的版本,RDD被Dataset取代了,相比于RDD,Dataset底层有着更丰富的优化,也同时拥有更优秀的性能。在2.0及以后的版本,RDD仍然被支持,但Spark官方强烈推荐使用性能更好的Dataset,这里我也会使用Dataset来作为示例。
先说下Spark shell,Spark shell是Spark提供的一种学习API的简单方法,同时它也是交互分析数据的强大工具。它可以基于Scala(在Java VM上运行,因此是使用现有Java库的好方法)或Python来使用。今天我们的例子将都在Spark shell中运行,至于编程将采用Scala
1.Spark Dataset的一些基本操作以及wordcount的实现
1) 启动spark shell,脚本存放在spark安装包的bin目录下,启动命令为:./bin/spark-shell
2) Spark的主要抽象是称为Dataset的分布式项目集合。Dataset可以从Hadoop InputFormats(如HDFS文件)创建,也可以通过转换其他Dataset创建。下面的例子是从Spark安装目录中的README文件文本中创建一个新的Dataset
scala> val textFile = spark.read.textFile("README.md")
textFile: org.apache.spark.sql.Dataset[String] = [value: string]
3) 我们可以对这个Dataset进行action操作来获取很多关于这个文件的属性值,或者进行transformation操作得到一个新的Dataset,也可以将transformation与action结合起来使用,关于transformation以及action的定义、区别以及一些其他的信息将在下一篇博客详细介绍。
scala> textFile.count()
res0: Long = 103
scala> textFile.first
res1: String = # Apache Spark
scala> val linesWithSpark = textFile.filter(line => line.contains("Spark"))//创建新Dataset
linesWithSpark: org.apache.spark.sql.Dataset[String] = [value: string]
scala> textFile.filter(line => line.contains("Spark")).count() //得到有多少行包含Spark字符
res2: Long = 15
4) Dataset的transformation以及action还可以用来进行更复杂的计算,比如现在我们想要知道README.md这个文件中单词数最多的那一行有多少单词。
scala> textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
res3: Long = 15
5) 因为scala读取文本文件是按照一行一行来的,所以第一个map方法将每一行的内容转换成了当前行的单词数,再在reduce方法中进行对比得到最终的结果。map以及reduce方法都是scala语言中的函数。因为scala运行在jvm上,还可以很简单的使用java中的方法。下面我们尝试使用java中的Math.max()方法来进行判断比较得到结果
scala> import java.lang.Math
import java.lang.Math
scala> textFile.map(line => line.split(" ").size).reduce((a, b) => Math.max(a, b))
res4: Int = 15
6) 大数据领域中一个非常常见的数据处理模式是MapReduce, Hadoop普及了这种模式。而Spark也可以轻松实现MapReduced的流程,下面是实现对README.md文件中每个单词进行出现次数统计的实例(也就是初学MapReduce时很经典的wordcount):
scala> val wordCounts = textFile.flatMap(line => line.split(" ")).groupByKey(x => x).count()
wordCounts: org.apache.spark.sql.Dataset[(String, Long)] = [value: string, count(1): bigint]
scala> wordCounts.collect()
res5: Array[(String, Long)] = Array((online,1), (graphs,1), (["Parallel,1), (["Building,1), (thread,1), (documentation,3), (command,,2), (abbreviated,1), (overview,1), (rich,1), (set,2), (-DskipTests,1), (name,1), (page](http://spark.apache.org/documentation.html).,1), (["Specifying,1), (stream,1), (run:,1), (not,1), (programs,2), (tests,2), (./dev/run-tests,1), (will,1), ([run,1), (particular,2), (option,1), (Alternatively,,1), (by,1), (must,1), (using,5), (you,4), (MLlib,1), (DataFrames,,1), (variable,1), (Note,1), (core,1), (more,1), (protocols,1), (guidance,2), (shell:,2), (can,7), (site,,1), (systems.,1), (Maven,1), ([building,1), (configure,1), (for,12), (README,1), (Interactive,2), (how,3), ([Configuration,1), (Hive,2), (system,1), (provides,1), (Hadoop-supported,1), (pre-built,...
2.缓存机制
Spark能够支持将数据缓存到内存中,当需要多次执行action操作时,如果在磁盘上则每次执行action的时候都会从磁盘加载数据,如果将其缓存到内存中能够显著提高再次执行action的读取速度。下面我们尝试将lineSpark进行缓存
scala> linesWithSpark.cache()
res6: linesWithSpark.type = [value: string]
scala> linesWithSpark.count()
res7: Long = 15
scala> linesWithSpark.count()
res8: Long = 15
使用Spark来分析和缓存一个100行左右的文本文件看起来有些大材小用,但Spark的缓存可以作用在非常大的数据集上,哪怕这些数据分布在成百上千个集群的节点上。
3.使用Spark构建一个独立的应用程序
Spark能够支持使用Scala、Java、Python等语言编写Spark应用程序,下面我们尝试使用Scala来编写一个简单的Spark程序统计README.md文件中包含字母a以及字母b的行各有多少,下面请看示例:
import org.apache.spark.sql.SparkSession
object SimpleApp {
def main(args: Array[String]) {
val logFile = "YOUR_SPARK_HOME/README.md" // YOUR_SPARK_HOME位置填写你的spark_home的路径
val spark = SparkSession.builder.appName("Simple Application").getOrCreate()
val logData = spark.read.textFile(logFile).cache()
val numAs = logData.filter(line => line.contains("a")).count()
val numBs = logData.filter(line => line.contains("b")).count()
println(s"Lines with a: $numAs, Lines with b: $numBs")
spark.stop()
}
}
之前我们使用Spark shell时可以直接使用SparkSession的实例,现在我们需要自己初始化作为程序一部分的SparkSession。我们通过调用SparkSession.builder来构建一个SparkSession,然后设置应用的名称,最后调用getOrCreate方法获得SparkSession的实例。
我们编写的这个程序依赖于Spark的API,我们通过maven或者sbt等工具来进行,这里我采用的是maven,pom.xml的主要内容如下:
<properties>
<spark.version>2.2.1</spark.version>
<scala.version>2.11</scala.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<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>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
接下来我们可以利用mvn clean package来将应用程序打成jar包,然后将jar包上传到服务器并提交给spark集群或者使用本地模式去执行,执行的命令为:
$ YOUR_SPARK_HOME/bin/spark-submit \
--class "SimpleApp" \
--master local[4] \
target/scala-2.11/simple-project_2.11-1.0.jar
本文介绍Spark Dataset的基本操作,包括从文件创建Dataset、执行过滤和计数等操作,以及使用缓存机制提升性能。并通过实例演示了wordcount的实现,展示了如何构建Spark应用程序。
1978

被折叠的 条评论
为什么被折叠?



