spark开发

1. 主要参考资料
http://spark.incubator.apache.org/docs/latest/scala-programming-guide.html
http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-82.pdf

2. 简介
每个Spark应用,都有一个驱动程序,它运行main函数,在集群上执行各种并行运算。Spark的最重要的抽象是RDD--Resilient Distributed Data(弹性分布式数据)。RDD存储数据,这些数据分布在Spark集群的各种节点上,这些数据可以进行并行计算。可以从一个HDFS文件或者类似的文件系统创建RDD,也可以从Scala的Collection创建RDD,也可以从另外一个RDD处理之后创建。RDD可以持久化到内存里。RDD可以自动从节点失效中恢复。

Spark第二个抽象是Shared Variables--共享变量,用于并行计算。Spark有两种共享变量:Broadcast varibles--广播变量,它在所有节点的内存里缓存一个值;Accumulators--累积量,它们只能被“加”起来,比如计数器或者是“求和”。

3. Spark程序的第一步是初始化SparkContext,它通知Spark如何获取一个集群:
    val sc = new SparkContext(master, appName, [sparkHome], [jars])

参数master指明集群的地址,是字符串,master可以是"local"--在本地单机运行,也可以是Spark或者Mesos集群的URL。
参数appName是Spark应用的名称,会在集群的web界面里显示出来。
参数sparkHome是spark的安装目录,注意,集群内所有节点的Spark必须安装在同样的目录下。
参数jars是打包后的Spark应用,是本地目录,这些Jar包会被复制发送到集群内的所有节点执行。

如果是运行Spark Shell,那么它会自从创建一个SparkContext,变量名sc,不要在Spark Shell创建新的SparkContext,不会生效的。在运行Spark Shell之前,可以指定环境变量,让Spark知道使用哪个集群,也可以用ADD_JARS环境变量把JARS添加到classpath。比如,如果想在spakr-shell在本地4核的cpu运行,需要如下方式启动:

$MASTER=local[4] ./spark-shell

这里的4,是启动4个工作线程。

如果要添加JARS,可以如下:
$MASTER=local[4] ADD_JARS=code.jar ./spark-shell

4. Master URLs

Master的URL有4中:
local,本地,单线程
local[K],本地,K个线程
spark://HOST:PORT,在spark集群上运行。
mesos://HOST:PORT,在Mesos集群上运行。

5. RDD-弹性分布式数据
Spark以RDD为核心概念开发的,它的运行也是以RDD为中心。有两种RDD:第一种是并行Collections,它是Scala collection,可以进行并行计算;第二种是Hadoop数据集,它是并行计算HDFS文件的每条记录,凡是Hadoop支持的文件系统,都可以进行操作。这两种RDD都以同样的方式处理。

6. RDD之 并行Collections
并行Collections由SparkContext的parallelize方法,在一个已经存在的Scala collection上创建。这个collection上的成员会被copy成分布式数据库,也就是copy到所有节点,于是就可以进行并行计算了。举例如下:

#scala的collection
scala> val data = Array(1, 2, 3, 4, 5)
data: Array[Int] = Array(1, 2, 3, 4, 5)

#并行collection
scala> val distData = sc.parallelize(data)
distData: spark.RDD[Int] = spark.ParallelCollection@10d13e3e

第一条语句创建一个Scala collection,第二条语句将它转化成并行collection。并行collection有一个重要参数,就是slices数,spark在进行计算的时候,每个slice对应一个task。通常,一个CPU对应2~4个slice。一般情况下,Sparkt会根据集群的状况,自动计算slice,也可以手动指定,比如说,paralize(data,10)就是指定了10个slice。

7. RDD之 Hadoop数据集

Spark支持在任何Hadoop能处理的文件系统上创建分布式数据集,包括本地文件系统,Amazon S3,Hypertable,HBase等等。Spark支持文本文件,序列文件,以及任何Hadoop的InputFormat。

比如,从文本文件创建数据集的方式如下:

scala> val distFile = sc.textFile("data.txt")
distFile: spark.RDD[String] = spark.HadoopRDD@1d4cee08

如果给distFile设置slice数量,形如sc.textFile("data.txt",5)。默认情况下,sparkt为data.txt的每个block块设置一个slice,注意,手工设置的slice数,只能比文件的block块数量大,不能比它小。

对于SequenceFile-序列文件,SparkContext的sequenceFile[k, v]函数将它转化成RDD。

对其他的Hadoop InputFormat,SparkContext.hadoopRDD方法处理。

8. RDD运算
RDD支持两种运算:变换transformation-从已有的RDD创建一个新的RDD,如map;或者从action中创建RDD,如reduce。

Spark的transformation都是lazy的,Spark会记下这些transformation,不立刻计算结果,直到action需要返回结果的时候再进行计算。

默认情况下,每个RDD的transformation都会重新计算,但如果将RDD用persisi持久化到内存里,或者缓存到内存里,它就不重新计算了,由此加快查询速度。

9. RDD持久化
如果一个RDD被持久化了,那么,每个节点都会存数这个RDD的所有slice,于是可以在内存进行计算,可以重用,这样可以让后来的action计算的更快,通常会把速度提高至少十倍。对迭代式计算来说,持久化非常关键。RDD的persisi方法和cache方法都可以进行持久化。RDD是容错的--如果它的任何部分丢失了,都会重新计算创建。

RDD有不同的存储方式,可以存在硬盘,或者内存,或者复制到所有节点。而chach函数只有一个默认的存储方式就是内存。

10. 共享变量-广播变量
广播变量--在集群的每个节点机器上都缓存一个只读的变量,比如说,每个节点都保存一份输入数据的只读缓存。

广播变量的使用方式:
scala> val broadcastVar = sc.broadcast(Array(1, 2, 3))
broadcastVar: spark.Broadcast[Array[Int] = spark.Broadcast(b5c40191-a864-4c7d-b9bf-d87e1a4e787c)

scala> broadcastVar.value
res0: Array[Int] = Array(1, 2, 3)

注意:创建了广播变量之后,就不能使用v了,要使用broadcaseCar;v值不能修改。

11. 共享变量-累计量:
只要是用作计数器counter或者求和sum,只能做add运算,例子如下:
scala> val accum = sc.accumulator(0)
accum: spark.Accumulator[Int] = 0

scala> sc.parallelize(Array(1, 2, 3, 4)).foreach(x => accum += x)
...
10/09/29 18:41:08 INFO SparkContext: Tasks finished in 0.317106 s

scala> accum.value
res2: Int = 10

上一篇:为什么不能访问django自带的索引页


下一篇:Struts2中Action接收参数的方法