1、spark2.0 工作依靠python2.6+或python3.4+ ,他可以使用标准的cpython解释器,所以说C libraries 例如numpy可以使用,它工作依靠pypy2.3+


bin/spark-submit

 bin/pyspark 去运行一个交互式的python shell。

        若果你想获得HDFS的数据,你需要建立spark与你的hdfs对应版本的联系,


    最后,你需要import一些spark的包到你的程序中,例如:


     from   pyspark   import   SparkContext ,   SparkConf


PySpark 需要 driver 和 workers 有相同的python版本,你可以利用PYSPARK_PYTHON 设置你喜欢的python版本。


2、初始化Spark


Spark程序第一个必须要做的是:创建一个SparkContexr对象,他会告诉Spark如何访问集群。在建立一个SparkContext对象之前你需要建立一个SparkConf对象,sparkConf对象包括了你的应用的信息。


conf = SparkConf().setAppName(appName).setMaster(master)
sc = SparkContext(conf=conf)


master =====> spark、mesos、yarn、或者local  运行在本地模型


在实际中,当运行程序在集群上时,不会设置master ,但当在本地测试或者单元测试时,你可以运用local




3、利用shell




4、弹性分布式数据集 RDDs


   4.1并行集合(parallelize colleactions)


    在程序中,并行的集合有SparkCinext的parallelize方法来实现,通过一个现存的集合或者可迭代数据,集合中的元素被复制去构建一个可以并行执行的分布式的数据集。eg:


data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data)


一旦被创建,这个分布式的数据集就可以并行执行。eg:我们可以利用distData.reduce(lambda a, b: a + b) 对list中的元素累加求和。通常情况下,你希望你的集群上的cpu有2-4个划分。通常情况下,spark会基于你的集群自动设定划分的数量。然而你也可以自己设定(e.g. sc.parallelize(data, 10)).,通过parallelize的第二个参数。

    4.2外部数据集


Cassandra, HBase, Amazon S3 等,Spark 支持 text files, SequenceFiles,和 any other Hadoop InputFormat.


       text file 的RDDs创建通过SparkContext的textFile的方法,这个方法利用文件的URI,以行的方式读取为一个集合,eg:


>>> distFile = sc.textFile("data.txt")


            (1)、如果利用本地文件系统的一个路径,这个文件必须在worker节点上可以以同样的路径访问。不论是拷贝文件到多有的files或者是利用共享文件系统。


            (2)、所有的Spark文件输入方法,包括textfile,支持目录,压缩文件或者通配符。rg:


 

textFile("/my/directory")

textFile("/my/directory/*.txt")

, and  textFile("/my/directory/*.gz")

.


            (3)、textfile方法有一个可选的第二参数设置文件的分区数量。


除了textflie方法,pyspark还支持其他几种data formats:


SparkContext.wholeTextFiles:可以读取一个目录下的多个文件


     

RDD.saveAsPickleFile

 and  SparkContext.pickleFile:支持保存一个RDD 序列化为一个python对象

        SequenceFile and Hadoop Input/Output Formats

注意:这些方式目前还是实验性的,将来或许会被SparkSQL所代替,因为SparkSQL是首选方法。

        4.3 保存和加载SequenceFiles

Writables 是不需要的。

>>> rdd = sc.parallelize(range(1, 4)).map(lambda x: (x, "a" * x ))
>>> rdd.saveAsSequenceFile("path/to/file")
>>> sorted(sc.sequenceFile("path/to/file").collect())
[(1, u'a'), (2, u'aa'), (3, u'aaa')]

        4.4

保存和加载其他Hadoop输入/输出格式:

        针对新的或老的hadoop MR API,pySpark 可以读取任何hadoop输入格式或者写任何hadoop输出格式,

5、RDD操作

    5.1 RDDs支持两种不同类型的操作

transformations:通过已经存在的数据集创建一个新的数据集

    actions:在数据集上执行完一个计算后,返回驱动程序一个值。

eg:

map:一个transformation  对数据集的每个元素执行一个函数,返回一个新的数据集

reduce:一个action,汇集RDD的所有元素利用一个函数,返回一个结果给驱动程序

reduceByKey : 返回一个分布式的数据集

    在Spark中所有的tansformation都是lazy的,并不是立刻计算它们的结果,而是记住这些转换。当一个action需要返回驱动程序一个结果时候,这些transfomaton才会执行。

默认情况下,对于每一个transformation,在其上运行一个action,可以使其执行。然而可以利用persist(或cache)方法,将元素防到集群上,当下一次请求时,可以快速的获得他。


    5.2 Spark 中的传递函数


    Spark的驱动程序在机上上运行时非常依赖与传递函数,有三种推荐方式去运行它:


    (1)、lambda表达式


    (2)、局部def 函数


    (3)、顶级功能模块


    5.3理解闭包


    Spark的一个难点是:在集群上执行代码时,理解变量和函数的范围和作用域。在变量的作用范围之外修改变量时混乱的源泉。


counter = 0
rdd = sc.parallelize(data)

# Wrong: Don't do this!!
def increment_counter(x):
    global counter
    counter += x
rdd.foreach(increment_counter)

print("Counter value: ", counter)



Local    VS     Cluster

    上述代码的表现是不确定的,或许可以按照你预想的方式运行。为了运行jobs,Spark将RDD的操作处理分解成任务,每一个都是一个执行者。在执行之前,Spark会计算任务task的闭包。闭包即在执行者执行RDD操作时,其执行所需的变量和方法对其是可见的。这些闭包会被序列化然后送到没一个执行者上边。

    在发送到执行者的闭包中的变量,现在是原始的副本,当counter 被引用时,他不再是driver上的counter。在driver的内存中还有一个counter ,但是其对executer(执行者)是不可见的。所以,counter最后的值还是0,因为所有对counter执行的操作都是在序列化的闭包中执行的。

    


 在local模式中,在某些场景中,foreach函数的执行会在相同的JVM中,或许会引用到相同的原始的counter,或许会真的uodate它。


    确保定义的行为在这些场景中,应该利用accumulator。在Spark中,Accumulator提供一种安全的更新变量的方式,挡在集群中执行时。


    通常情况下,在利用loops或local结构定义方法时,闭包不应该改变全局变量的值。Spark,没有定义或者保证在闭包之外修改变量的行为。有一些代码,活血在local模式下可以执行,但是那只是意外,这些低吗在分布式的情况下不会跟期待的那样执行。


    5.5 输出RDD的元素


rdd.foreach(println) or rdd.map(println).,在单机模式下,这有可能会会按照所期待的那样输出。但是在集群下,并不行。

    输出driver中的所有元素利用collect(),可能会导致内存溢出,因为collect()会将所有的Rdd放到单机上。如果只是想输出RDD的少数部分元素,一种安全的方式是利用take()。