Spark官方2 ---------Spark 编程指南(1.5.0)

概述

在高层次上,每个Spark应用程序都由一个运行用户main方法的driver program组成,并在集群上执行各种 parallel operations。Spark提供的主要抽象是resilient distributed dataset (RDD),它是可以并行操作的群集节点之间分配的元素的集合。RDD是由Hadoop文件系统(或任何其他Hadoop支持的文件系统)中的文件或驱动程序中的现有Scala集合开始,并进行转换创建的。用户还可以要求Spark在内存中保留RDD,从而在并行操作中有效地重用RDD。最后,RDD自动从节点故障中恢复。

Spark中的第二个抽象是可以在并行操作中使用的共享变量。默认情况下,当Spark将并行功能作为一组任务在不同节点上运行时,它会将功能中使用的每个变量的副本发送到每个任务。有时,需要在任务之间或任务和驱动程序之间共享一个变量。Spark支持两种类型的共享变量:广播变量,可用于缓存所有节点上的内存中的值,以及累加器,它们只是“添加”到诸如计数器和总和之间的变量。

本指南显示了Spark支持的每种语言中的每个功能。可以通过启动Spark的交互式shell 进行学习- Scala shell的bin / spark-shell或Python的bin / pyspark。

 

依赖

Spark 1.5.0适用于Java 7及更高版本。如果您使用Java 8,Spark可以简单地编写函数来支持lambda表达式,否则可以使用org.apache.spark.api.java.function包中的类。

要在Java中编写Spark应用程序,需要在Spark上添加依赖关系。Spark可通过Maven Central获得:

groupId = org.apache.spark
artifactId = spark-core_2.10
version = 1.5.0

另外,如果您希望访问HDFS群集,则需要为您的HDFS版本的hadoop-client添加依赖关系。一些常见的HDFS版本标签列在第三方发行版页面上。

groupId = org.apache.hadoop
artifactId = hadoop-client
version = <your-hdfs-version>

最后,您需要将一些Spark类导入到程序中。添加以下行:

import org.apache.spark.api.java.JavaSparkContext
import org.apache.spark.api.java.JavaRDD
import org.apache.spark.SparkConf

 

Resilient Distributed Datasets (RDDs)

 Spark围绕着弹性分布数据集(RDD)的概念,RDD是一种容错的并行操作元素集合。创建RDD有两种方法:并行化驱动程序中的现有集合,或者在外部存储系统(如共享文件系统,HDFS,HBase或提供Hadoop InputFormat的任何数据源)中引用数据集。

Parallelized Collections

External Datasets

Spark可以从Hadoop支持的任何存储源创建分布式数据集,包括本地文件系统,HDFS,Cassandra,HBase,Amazon S3等。Spark支持文本文件,SequenceFiles和任何其他Hadoop InputFormat。

文本文件RDD可以使用SparkContext的textFile方法创建。该方法获取文件的URI(机器上的本地路径,或hdfs://,s3n://,etc URI),并将其作为行的集合读取。这是一个示例调用:








JavaRDD<String> distFile = sc.textFile("data.txt");

 一旦创建,distFile可以通过数据集操作来执行。例如,我们可以使用map来添加所有行的大小,并按如下所示减少操作:distFile.map(s - > s.length())。reduce((a,b) - > a b)。

 

有关Spark的阅读文件的一些注意事项:

 

 

 

RDD Persistence

 Spark中最重要的功能之一是在操作中持久(或缓存)内存中的数据集。当您持有RDD时,每个节点都会将其计算的任何分区存储在内存中,并将在action操作重用该数据集(或从其导出的数据集)。这可以使未来的动作快得多(通常超过10倍)。缓存是迭代算法和快速交互使用的关键工具。

您可以使用其上的persist()或cache()方法标记要持久化的RDD。第一次action时,它将被保存在节点的内存中。Spark的缓存是容错的 - 如果RDD的任何分区丢失,它将使用最初创建的转换自动重新计算。

此外,可以使用不同的存储级别存储每个持久化的RDD,从而允许您将数据集保留在磁盘上,或者将其作为序列化的Java对象保存在内存中(以节省空间),将其跨节点复制。通过将StorageLevel对象(Scala,Java,Python)传递给persist()来设置这些级别。cache()方法是使用默认存储级别的简写,即StorageLevel.MEMORY_ONLY(在内存中存储反序列化的对象)。全套存储级别为:

 

Storage LevelMeaning
MEMORY_ONLY Store RDD as deserialized Java objects in the JVM. If the RDD does not fit in memory, some partitions will not be cached and will be recomputed on the fly each time they're needed. This is the default level.
MEMORY_AND_DISK Store RDD as deserialized Java objects in the JVM. If the RDD does not fit in memory, store the partitions that don't fit on disk, and read them from there when they're needed.
MEMORY_ONLY_SER 
(Java and Scala)
Store RDD as serialized Java objects (one byte array per partition). This is generally more space-efficient than deserialized objects, especially when using a fast serializer, but more CPU-intensive to read.
MEMORY_AND_DISK_SER 
(Java and Scala)
Similar to MEMORY_ONLY_SER, but spill partitions that don't fit in memory to disk instead of recomputing them on the fly each time they're needed.
DISK_ONLY Store the RDD partitions only on disk.
MEMORY_ONLY_2, MEMORY_AND_DISK_2, etc. Same as the levels above, but replicate each partition on two cluster nodes.
OFF_HEAP (experimental) Similar to MEMORY_ONLY_SER, but store the data in off-heap memory. This requires off-heap memory to be enabled.

 

 

即使没有用户调用persist,Spark也会自动将shuffle操作中的一些中间数据(例如reduceByKey)保留下来。这样做是为了避免重新计算整个输入,如果在shuffle期间节点出现故障。如果计划重用它,我们仍然建议用户在生成的RDD上调用persist 。

Which Storage Level to Choose?

 Spark的存储级别旨在提供内存使用和CPU效率之间的不同权衡。我们建议您通过以下过程来选择一个:

如果您的RDD适合于默认存储级别(MEMORY_ONLY),默认使用这种方式。这是CPU效率最高的选项,允许RDD上的操作尽可能快地运行。

其他情况,请尝试使用MEMORY_ONLY_SER并选择一个快速序列化库,使对象更加节省空间,但仍然能够快速访问。(Java和Scala)

不要溢出到磁盘,除非计算您的数据集的功能是昂贵的,或者它们过滤大量的数据。否则,重新计算分区可能与从磁盘读取分区一样快。

如果您想要快速故障恢复,请使用复制的存储级别(例如,如果使用Spark来提供来自Web应用程序的请求)。所有存储级别通过重新计算丢失的数据来提供完整的容错能力,但复制的数据可让您继续在RDD上运行任务,而无需重新计算丢失的分区。

Removing Data

Spark会自动监视每个节点的缓存使用情况,并以最近最少使用(LRU)方式丢弃旧的数据分区。如果您想手动删除RDD,而不是等待它脱离缓存,请使用RDD.unpersist()方法。

 

 

 

 

共享变量

Broadcast Variables

广播变量允许程序员在每个机器上保留缓存的只读变量,而不是使用任务运送副本。例如,可以使用它们以有效的方式为每个节点提供大型输入数据集的副本。Spark还尝试使用高效的广播算法分发广播变量,以降低通信成本。

Spark action由“shuffle”操作拆分成不同stage执行。Spark自动广播每个阶段任务所需的公共数据。以这种方式广播的数据以序列化形式缓存,并在运行每个任务之前反序列化。这意味着,显式创建广播变量仅在跨多个阶段的任务需要相同数据或者以反序列化格式缓存数据很重要时才有用。

广播变量通过调用SparkContext.broadcast(v)从变量v创建。广播变量是围绕v的包装器,其值可以通过调用value方法来访问。下面的代码显示:

Broadcast<int[]> broadcastVar = sc.broadcast(new int[] {1, 2, 3});

broadcastVar.value();

创建广播变量后,应在群集中运行的任何函数中使用它而不是值v,以便v不会多次发送到节点。另外,在广播之后不应修改对象v,以便确保所有节点获得与广播变量相同的值(例如,如果该变量稍后发送到新节点)。

 

posted @ 2017-09-12 18:01  Mr.Ming2  阅读(257)  评论(0编辑  收藏  举报