Spark 1.5.1快速指南

说明:本翻译基本遵照Spark的官方翻译,但是某些不太顺口的地方还是做了一下处理,请原谅我poor的外语能力。官网链接:http://spark.apache.org/docs/latest/quick-start.html

使用Spark Shell进行交互分析

基本操作

Spark的shell提供了一种简单的方式来学习Api,同时它也是一个强大的具有交互功能的数据分析工具。无论是Python还是Scala(Scala运行在Java虚拟机上,同时能够非常方便的使用Java类库),它都是可用的。在Spark的安装目录中使用如下命令来启动Spark Shell:

Scala

.bin/spark-shell

Python

.bin/pyspark

Spark中最主要的抽象概念是一个分布式的记录集合,即弹性分布式数据集(RDD)。RDD可以由Hadoop的输入来创建(比如HDFS上的文件)或者由其它RDD转换而来。下面让我们使用Spark源目录中的README文件内容创建一个RDD。

>>>textFile = sc.textFile("README.md")

RDD可以使用动作(action)来返回值,或者使用转换(transformations)操作变成新的RDD。下面是一些动作的示例:

>>>textFile.count()    #这个RDD中记录的条目
126

>>>textFile.first()    #这个RDD的第一条记录
u'# Apache Spark'

现在让我们使用一个转换操作。我们将使用filter转换操作来得到一个新的RDD,这个RDD是原来文件记录的一个子集(过滤)

>>>linesWithSpark = textFile.filter(lambda line: "Spark" in line)

我们可以将动作和转换操作组合在一起成为一个链

>>>textFile.filter(lambda line: "Spark" in line).count()    #有多少行含有"Spark"?
15
更多关于RDD的操作

RDD的动作和转换可以用于做复杂的计算。让我们实现一个任务,输出是含有最多单词的那一行含有多少个单词:

Scala

scala> textFile.map(line => line.split(" ").size).reduce((a, b) => if(a > b) a else b)
res4: Long=15

Python

>>>textFile.map(lambda line : len(line.split(" "))).reduce(lambda a, b : a if(a > b) else b)
15

上面首先将每一行映射到了一个整数值,即创建了一个新的RDD。然后在新的RDD上调用了reduce动作来寻找最大的行单词数。map与reduce的入参形式是Python中的匿名函数(lambdas),但是我们也可以使用Python的top-level函数(这个不好解释,类似于函数中嵌套函数,top-level就是外面那个?)。例如,我们可以定义max函数来使代码更加便于理解。

>>>def max(a, b):
...     if a > b:
...         return a
...     else:
...         return b

>>>textFile.map(lambda line: len(line.split())).reduce(max)
15

MapReduce是一个典型的数据流格式,Hadoop的发展使得这种处理方式变得非常流行。Spark可以很方便的实现MapReduce:

>>>wordCounts = textFile.flatMap(lambda line: line.split()).map(lambda word: (word, 1)).reduceByKey(lambda a, b: a + b)

这里,我们将flatMap,Map和reduceByKey转换操作(reduceByKey我记得是action啊,这里官网使用了transformations)组合在一起来计算文件中每一个单词的数量,并返回一个RDD,形式是(String,int)型的键值对。
为了在shell中计算单词的数量,我们可以使用collect动作:

>>>wordCounts.collect()
[(u'and', 9), (u'A', 1), (u'webpage', 1), (u'README', 1), (u'Note', 1), (u'"local"', 1), (u'variable', 1), ...]
缓存

Spark也支持将数据集合缓存在整个集群的内存中。这对于数据的重用非常方便,比如当我们检索一个小型的”hot”数据集(其实就是使用频率比较高的)或者运行一些迭代算法比如PageRank.作为一个简单的例子,让我们把上面的linesWithSpark数据集缓存起来:

Scala

scala> linesWithSpark.cache()
res7: spark.RDD[String] = spark.FilteredRDD@17e51082

scala> linesWithSpark.count()
res8: Long = 19

scala> linesWithSpark.count()
res9: Long = 19

使用Spark来对一个只有100行的文本文件进行探索和缓存看起来似乎有点”愚蠢”。但是这些方法也可以运行在超大数据集合上,即使这些数据横跨了数十甚至数百个节点,这个可能比较有趣。你依然可以将bin/spark-shell连接到集群上进行这些交互式的操作,具体可以参考programming guide(这个后续翻译)。

独立应用

假设我们希望使用Spark的API来编写独立的应用程序。我们将分别使用Scala(sbt),Java(Maven)以及python通过一个简单的应用来做一个示范。

Scala

/* SimpleApp.scala*/
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf

object SimpleApp{
    def main(args: String[]){
        val logFile = "YOUR_SPARK_HOME/README.md"
        val conf = new SparkConf().setAppName("Simple Application")
        val sc = new SparkContext(conf)
        val logData = sc.textFile(logFile, 2).cache()
        val numAs = logData.filter(line => line.contains("a")).count()
        val numBs = logData.filter(line => line.contains("b")).count()
        println("Line with a: %s,Line with b: %s".format(numAs, numBs))
    }
}

Java

/* SimpleApp.java */
import org.apache.spark.api.java.*;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.function.Function;

public class SimpleApp {
  public static void main(String[] args) {
    String logFile = "YOUR_SPARK_HOME/README.md"; // Should be some file on your system
    SparkConf conf = new SparkConf().setAppName("Simple Application");
    JavaSparkContext sc = new JavaSparkContext(conf);
    JavaRDD<String> logData = sc.textFile(logFile).cache();

    long numAs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("a"); }
    }).count();

    long numBs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("b"); }
    }).count();

    System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs);
  }
}

Python

"""SimpleApp.py"""
from pyspark improt SparkContext

logFile = "YOUR_SPARK_HOME/README.md"  # Should be some file on your system
sc = SparkContext("local", "Simple App")
logData = sc.textFile(logFile).cache()

numAs = logData.filter(lambda s: 'a' in s).count()
numBs = logData.filter(lambda s: 'b' in s).count()
print("Lines with a: %i, lines with b: %i" % (numAs, numBs))

这个项目只是统计了一个文本文件中包含了字符‘a’的行数以及包含字符’b’的行数。记着你需要将
YOUR_SPARK_HOME替换成Spark的安装目录。对于使用Scala和Java的例子,我们使用了SparkContext来创建RDD。我们可以将Python函数转到Spark上来,它们所引用的任何变量都会被自动序列化。对于使用了自定义类或者第三方库的应用,我们也可以将它们打包成.zip文件,然后通过spark-submit的–py-files参数添加进来(使用spark-submit –help获取详情)。SimpleApp太简单了了,不需要依赖任何其它代码。

我们可以通过bin/spark-submit脚本来运行上面的应用:

# Use spark-submit to run your application
$ YOUR_SPARK_HOME/bin/spark-submit \
  --master local[4] \
  SimpleApp.py
...
Lines with a: 46, Lines with b: 23

猜你喜欢

转载自blog.csdn.net/solo_sky/article/details/49582745