分享

Spark 快速入门(版本spark1.1.1)

本帖最后由 howtodown 于 2014-12-9 20:02 编辑


问题导读:


1.spark RDD的transformation和action的作用是什么?
2.spark RDD的transformation和action能够如何组合?









本教程快速介绍了Spark的使用。 首先我们介绍了通过Spark 交互式shell调用API( Python或者scala代码),然后演示如何使用Java, Scala或者Python编写独立程序。 你可以查看Spark编程指南了解完整的参考。
开始下面的快速入门之前,首先需要到Spark网站下载一份打包好的spark。 既然本教程中我们不使用HDFS,你可以随便下载一个适配任何Hadoop的版本的Spark。
本教程翻译时的Spark版本为1.1.1
使用Spark进行交互式分析基本操作
Spark shell提供了一个简单方式去学习API,它也是一个交互式分析数据的强大工具。 你既可以使用Scala(运行在JVM之上,所以可以使用众多的Java库),也可以使用Python。运行Spark文件夹下的的命令:
  1. ./bin/spark-shell
复制代码

Spark最主要的一个抽象出来的概念就是分布式的数据集合, 也就是弹性分布式数据集Resilient Distributed Dataset (RDD). RDD可以从Hadoop InputFormats (比如HDFS文件)创建, 也可以通过其它RDD转换(transforming)得到。 让我们从Spark源代码文件夹下的README文件创建一个RDD:
  1. scala> val textFile = sc.textFile("README.md")
  2. textFile: spark.RDD[String] = spark.MappedRDD@2ee9b6e3
复制代码


RDD包含action,可以返回数据, 也包含transformation,返回新的RDD的指针。 先看一些action的例子:
  1. scala> textFile.count() // 此RDD中的item的数量
  2. res0: Long = 126
  3. scala> textFile.first() // 此RDD第一个item
  4. res1: String = # Apache Spark
复制代码


现在再看一个转换的例子。我们使用filter返回一个新的RDD, 新的RDD是文件中item的一个子集。
  1. scala> val linesWithSpark = textFile.filter(line => line.contains("Spark"))
  2. linesWithSpark: spark.RDD[String] = spark.FilteredRDD@7dd4af09
复制代码


将transformation和action串起来:
  1. scala> textFile.filter(line => line.contains("Spark")).count() // How many lines contain "Spark"?
  2. res3: Long = 15
复制代码


更多的RDD操作
RDD的transformation和action可以组成起来完成复杂的计算。 比如查找包含最多单词的一行:
  1. scala> textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
  2. res4: Long = 15
复制代码


第一步map一行包含的单词数到一个整数, 第二步调用reduce得到最大的单词数。map和reduce的参数都是lambda表达式(closures), 可以调用 Scala/Java库. 例如我们很容易的调用在其它地方声明的方法。 这里我们使用Math.max()函数简化代码:
  1. scala> import java.lang.Math
  2. import java.lang.Math
  3. scala> textFile.map(line => line.split(" ").size).reduce((a, b) => Math.max(a, b))
  4. res5: Int = 15
复制代码


一个通用的数据流模式就是MapReduce,在Hadoop中相当流行. Spark实现MapReduce流很容易:
  1. scala> val wordCounts = textFile.flatMap(line => line.split(" ")).map(word => (word, 1)).reduceByKey((a, b) => a + b)
  2. wordCounts: spark.RDD[(String, Int)] = spark.ShuffledAggregatedRDD@71f027b8
复制代码


此处我们使用flatMap, map 和 reduceByKey转换来计算文件中每个单词的频度。 为了收集单词频度结果,我们可以调用collect action:
  1. scala> wordCounts.collect()
  2. res6: Array[(String, Int)] = Array((means,1), (under,2), (this,3), (Because,1), (Python,2), (agree,1), (cluster.,1), ...)
复制代码


缓存
Spark也支持将数据集放入集群的内存中缓存起来. 当数据重复访问时特别有用, 比如查询一个小的 “hot”数据集或者运行一个交互式算法PageRank. 看一个简单的例子, 我们把上面的linesWithSpark数据集缓存起来:
  1. scala> linesWithSpark.cache()
  2. res7: spark.RDD[String] = spark.FilteredRDD@17e51082
  3. scala> linesWithSpark.count()
  4. res8: Long = 15
  5. scala> linesWithSpark.count()
  6. res9: Long = 15
复制代码


当然使用Spark缓存一个100行的文本文件看起来有些傻,我们只是做个示范。 你可以将它用在非常大的数据集上,即使它们可能横跨几十甚至上百个节点。你也可以使用bin/spark-shell交互式实现此功能, 就像开发指南中描述的那样。
独立应用
下面我们想说一下怎样使用Spark API编写一个独立的应用程序。 这里使用Scala (SBT构建工具)和Java举例。 (Python官方文档中有,译者未翻译)
  1. /* SimpleApp.scala */
  2. import org.apache.spark.SparkContext
  3. import org.apache.spark.SparkContext._
  4. import org.apache.spark.SparkConf
  5. object SimpleApp {
  6.   def main(args: Array[String]) {
  7.     val logFile = "YOUR_SPARK_HOME/README.md" // Should be some file on your system
  8.     val conf = new SparkConf().setAppName("Simple Application")
  9.     val sc = new SparkContext(conf)
  10.     val logData = sc.textFile(logFile, 2).cache()
  11.     val numAs = logData.filter(line => line.contains("a")).count()
  12.     val numBs = logData.filter(line => line.contains("b")).count()
  13.     println("Lines with a: %s, Lines with b: %s".format(numAs, numBs))
  14.   }
  15. }
复制代码


这个程序统计Spark README文件中包含字符ab的行数。 注意你需要用你实际的Spark路径替换 YOUR_SPARK_HOME。 不像上面的Spark shell的例子, 我们初始化一个SparkContext 作为程序的一部分.
我们将一个SparkConf对象传给SparkContext的构造函数, 它包含了我们程序的信息。
我们的程序依赖Spark API,所以我们包含一个sbt配置文件:simple.sbt 指明Spark是一个依赖, 这个文件也增加了Spark依赖的仓库(repository):
  1. name := "Simple Project"
  2. version := "1.0"
  3. scalaVersion := "2.10.4"
  4. libraryDependencies += "org.apache.spark" %% "spark-core" % "1.1.1"
复制代码


为了保证sbt工作正常,我们需要将SimpleApp.scala和simple.sbt放入典型的sbt项目布局的文件夹中。 如此一来我们将应用代码可以打包成一个jar文件, 然后使用spark-submit脚本来运行此程序。
  1. # Your directory layout should look like this
  2. $ find .
  3. .
  4. ./simple.sbt
  5. ./src
  6. ./src/main
  7. ./src/main/scala
  8. ./src/main/scala/SimpleApp.scala
  9. # Package a jar containing your application
  10. $ sbt package
  11. ...
  12. [info] Packaging {..}/{..}/target/scala-2.10/simple-project_2.10-1.0.jar
  13. # Use spark-submit to run your application
  14. $ YOUR_SPARK_HOME/bin/spark-submit \
  15.   --class "SimpleApp" \
  16.   --master local[4] \
  17.   target/scala-2.10/simple-project_2.10-1.0.jar
  18. ...
  19. Lines with a: 46, Lines with b: 23
复制代码


或者使用Java
  1. /* SimpleApp.java */
  2. import org.apache.spark.api.java.*;
  3. import org.apache.spark.SparkConf;
  4. import org.apache.spark.api.java.function.Function;
  5. public class SimpleApp {
  6.   public static void main(String[] args) {
  7.     String logFile = "YOUR_SPARK_HOME/README.md"; // Should be some file on your system
  8.     SparkConf conf = new SparkConf().setAppName("Simple Application");
  9.     JavaSparkContext sc = new JavaSparkContext(conf);
  10.     JavaRDD<String> logData = sc.textFile(logFile).cache();
  11.     long numAs = logData.filter(new Function<String, Boolean>() {
  12.       public Boolean call(String s) { return s.contains("a"); }
  13.     }).count();
  14.     long numBs = logData.filter(new Function<String, Boolean>() {
  15.       public Boolean call(String s) { return s.contains("b"); }
  16.     }).count();
  17.     System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs);
  18.   }
  19. }
复制代码


这个程序统计Spark README文件中包含字符ab的行数。. 注意你需要用你实际的Spark路径替换 YOUR_SPARK_HOME。 不像上面的Spark shell的例子, 我们需要一个JavaSparkContext对象. 我们也创建了RDD (JavaRDD)然后运行transformations. 最后我们传递给Spark一个function对象, 这个function对象是一个匿名类,继承于 spark.api.java.function.Function. Spark开发指南描述了细节. (译者注: 这是Java 7的语法, 通过Java 8 Lambda表达式,上面的代码和scala一样的简化)
为了编译此程序,我们需要写一个Maven pom.xml文件, 增加Spark作为依赖. 注意Spark artifact带有Scala的版本.
  1. <project>
  2.   <groupId>edu.berkeley</groupId>
  3.   <artifactId>simple-project</artifactId>
  4.   <modelVersion>4.0.0</modelVersion>
  5.   <name>Simple Project</name>
  6.   <packaging>jar</packaging>
  7.   <version>1.0</version>
  8.   <dependencies>
  9.     <dependency> <!-- Spark dependency -->
  10.       <groupId>org.apache.spark</groupId>
  11.       <artifactId>spark-core_2.10</artifactId>
  12.       <version>1.1.1</version>
  13.     </dependency>
  14.   </dependencies>
  15. </project>
复制代码


使用Maven项目的布局:
  1. $ find .
  2. ./pom.xml
  3. ./src
  4. ./src/main
  5. ./src/main/java
  6. ./src/main/java/SimpleApp.java
复制代码


现在,我们使用Maven打包并使用./bin/spark-submit执行此程序.
  1. # Package a jar containing your application
  2. $ mvn package
  3. ...
  4. [INFO] Building jar: {..}/{..}/target/simple-project-1.0.jar
  5. # Use spark-submit to run your application
  6. $ YOUR_SPARK_HOME/bin/spark-submit \
  7.   --class "SimpleApp" \
  8.   --master local[4] \
  9.   target/simple-project-1.0.jar
  10. ...
  11. Lines with a: 46, Lines with b: 23
复制代码


深入了解
亲爱的读者,恭喜你运行了你的第一个Spark应用程序!
你肯定不仅仅满足于此,以下是更多的深入学习的资料:
  • 深度学习API和其它组件, 请参照Spark编程指南
  • 学习在集群中运行程序,访问 发布概览.
  • 最后, Spark发布包中的examples文件夹下包含几个例子 (Scala, Java, Python). 你可以运行它们:
  1. # For Scala and Java, use run-example:
  2. ./bin/run-example SparkPi
  3. # For Python examples, use spark-submit directly:
  4. ./bin/spark-submit examples/src/main/python/pi.py
复制代码










http://colobu.com/2014/12/08/spark-quick-start/

已有(7)人评论

跳转到指定楼层
chinaboy2005 发表于 2014-12-9 20:18:29
学习中,资料挺有用的
回复

使用道具 举报

liusiping 发表于 2014-12-10 00:38:42
回复

使用道具 举报

hadoop521 发表于 2014-12-10 13:17:57
很有用 谢谢楼主
回复

使用道具 举报

hb1984 发表于 2014-12-10 17:11:35
谢谢楼主分享。         
回复

使用道具 举报

alprah 发表于 2014-12-10 19:29:47
回复

使用道具 举报

liusiping 发表于 2014-12-12 13:01:06
学习中 赞分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条