Spark 2.0 Programming Guide 翻译(PySpark)

1、spark2.0 工作依靠python2.6+或python3.4+ ,他可以使用标准的cpython解释器,所以说C libraries 例如numpy可以使用,它工作依靠pypy2.3+
       在python下运行spark应用,利用 bin/spark-submit  脚本(在spark 目录下),可以load  spark的java/scala的libraaies并且允许你提交应用到集群。可以利用 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)
appName ====> 是你显示在集群用户界面的应用程序名称
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外部数据集
    PySpark可以创建通过hadoop创建分布式数据集,不分其来源是什么,包括你的本地文件系统,HDFS,Cassandra, HBase, Amazon S3 等,Spark 支持 text files, SequenceFiles,和 any other Hadoop InputFormat.
       text file 的RDDs创建通过SparkContext的textFile的方法,这个方法利用文件的URI,以行的方式读取为一个集合,eg:
>>> distFile = sc.textFile("data.txt")
利用spark读取文件的一些笔记:
            (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
           SequenceFiles 可以通过指定的路劲save和加载,       可以指定键值,但是对于标准的 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中的元素:rdd.foreach(println) or rdd.map(println).,在单机模式下,这有可能会会按照所期待的那样输出。但是在集群下,并不行。
    输出driver中的所有元素利用collect(),可能会导致内存溢出,因为collect()会将所有的Rdd放到单机上。如果只是想输出RDD的少数部分元素,一种安全的方式是利用take()。



























































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值