Spark(1)-初识Pyspark

一、前言
(注:以下操作都是基于python语言,根据官网guide总结。)

1、RDDs
spark中最重要的抽象是RDDs(Resilient Distributed Datasets弹性分布式数据集),可以简单的把RDDs理解成一个提供了许多操作接口的分布式数据集合,和一般数据集不同的是,其实际数据分布存储于一批机器中(内存或磁盘中)。

RDDs可以通过hadoop文件系统或者驱动程序中已经存在的Scala数据集进行创建和转换,同时用户也可以使其常驻内存,进而通过并行操作高效利用,最后还可以从失败的节点恢复。

2、共享变量

在并行计算中,有时需要任务间共享,有时则需要任务和驱动程序之间共享。
spark支持两种类型的共享:

broadcast variables,用于在所有节点的内存中缓存某个值;

accumulators,累加操作。

二、连接Spark

版本—————————-如果是Spark 2.1.1 ,需要python2.6+ or python 3.4+。

为了在python中运行,在Spark目录中使用bin/spark-submit脚本,主要是加载java库,并向集群提交程序。

也可以在python shell 交互界面使用pyspark包

from pyspark import SparkContext, SparkConf

注意:在集群模式中,驱动和worker的python版本必须一样。

三、初始化spark运行环境

1、SparkContext

这玩意是啥?

假设Spark集群是服务器,那么用户这边的驱动程序好比是客户端,那么SparkContext就是客户端的核心,是Spark的入口,其方法可以用来连接集群,创建RDD、广播变量等。也就是说几乎所有的spark操作都是围绕这个类进行的。

通常情况下一个驱动程序只会有一个SparkContext实例。

具体接口如下:

class pyspark.SparkContext(master=None, appName=None, sparkHome=None, pyFiles=None, environment=None, batchSize=0, serializer=PickleSerializer(), conf=None, gateway=None, jsc=None, profiler_cls=<class 'pyspark.profiler.BasicProfiler'>)

在pyspark中,初始化主要是创建一个SparkContext对象,告诉程序怎么找到集群,具体分两步:
首先,配置应用程序的信息:

SparkConf为Spark配置类,包含了名称,执行环境,master等信息,一旦被传送给spark就不可更改。

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

然后,用配置信息创建对象:

sc = SparkContext(conf=conf)

2、spark-submit

向集群提交代码或者配置信息的脚本,具体方法如下:

首先,将代码和相关依赖都打包(对于python,最好是.zip or .egg);

然后就是脚本格式:

./bin/spark-submit \
  --class <main-class> \  #程序入口(e.g. org.apache.spark.examples.SparkPi)
  --master <master-url> \  #master(e.g. spark://23.195.26.187:7077);
  --deploy-mode <deploy-mode> \  #集群点 (cluster) 还是外部客户端(client) ,默认是(client) 
  --conf <key>=<value> \  #key=value形式的配置信息
  ... # other options
  <application-jar> \   #.py文件即可,或者使用--py-files将.zip, .egg or .py加入到搜索路径中。
  [application-arguments   #入口的方法的参数

Master-url

local——本地单一worker线程

local[K]——-K个worker线程中的某个,K最好是CPU核数

local[*]——-所有的worker线程一起运行,数量等于CPU核数

spark://HOST:PORT,其他的具体看doc。

例如:

# 单独的节点运行python程序
cluster
./bin/spark-submit \
  --master spark://207.184.161.138:7077 \
  examples/src/main/python/pi.py \
  1000

3、shell

PySpark shell中,sc作为默认的SparkContext实例已经被创建,可以直接使用。
参数简介:
–master 选择集群中的mater;
–py-files 将 .zip, .egg or .py 文件加入运行时路径,用逗号隔开
–packages 加入不同依赖包,这些需要pip手动安装。

$ ./bin/pyspark --master local[4] --py-files code.py

使用IPython的话,需要设置环境变量:

$ PYSPARK_DRIVER_PYTHON=ipython ./bin/pyspark
sc = SparkContext("local", "App Name", pyFiles=['MyFile.py', 'lib.zip', 'app.egg'])

四、RDD

分布式数据集

1 并行化数据
将驱动程序中的数据集复制成一个分布式的数据集,之后就可以进行reduce等操作了。

data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data)//parallelize(data,numOfPartitions)第二个参数默认自动根据集群个数将数据集划分为若干部分

distData.reduce(lambda a, b: a + b)

2 转化RDDs

只要是Hadoop支持的外部存储格式,PySpark也支持。包括了 local file system, HDFS, Cassandra, HBase, Amazon S3, etc. Spark supports text files, SequenceFiles, and any other Hadoop InputFormat.

2.1 从外部格式转换

具体方法就是:

>>> distFile = sc.textFile("data.txt")#该方法第二个参数同样可以对数据集进行划分
>>> distFile = sc.textFile("/my/directory/*.gz")#对文件夹进行操作

#或者python提供了多个其他格式

SparkContext.wholeTextFiles #读取包含多个text文件的文件夹,按 (filename, content) 返回多个

#序列化

RDD.saveAsPickleFile 
SparkContext.pickleFile#将RDD存储为python序列化对象

>>> 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')]

3、RDD Operations

主要是两类操作:

transformations,从现存的数据集产生新数据集,比如map;

actions,对数据集进行计算,然后返回给驱动程序一个值,比如reduce;

transformations操作并不会在得到数据后就立马进行计算,而是先记住有这个操作,直到action需要给驱动返回结果的时候再进行计算,这样整个系统不需要在不必要的时候保存transformations后的数据,使得运行高效省力。

每次action需要的时候,都重新计算,当然在频繁查询的情况下也可以使用persist()使转换后的RDD常驻内存、磁盘等。

基本操作

lines = sc.textFile("data.txt")
lineLengths = lines.map(lambda s: len(s))
#lineLengths.persist()  必要的时候

totalLength = lineLengths.reduce(lambda a, b: a + b)

使RDD常驻内存,然后过滤所有关键字行:

logData = sc.textFile(logFile).cache()
errors = logData.filter(lambda line: "ERROR" in line)

函数导入

if __name__ == "__main__":
    def myFunc(s):
        words = s.split(" ")
        return len(words)

    sc = SparkContext(...)
    sc.textFile("file.txt").map(myFunc)

使用对象

class MyClass(object):
    def __init__(self):
        self.field = "Hello"
    def doStuff(self, rdd):
        return rdd.map(lambda s: self.field + s)

需要将完整的对象提交给集群,以下将field作为局部变量传递。

def doStuff(self, rdd):
    field = self.field
    return rdd.map(lambda s: field + s)

五、理解闭包
在集群中执行代码时,变量方法的作用域和生命周期是一大难点。

闭包:可以在函数的外部(即子函数),直接读取该函数的局部变量。

spark将RDD操作分成多个任务,每一个都被不同的执行器执行,在执行之前,spark会首先计算任务的闭包。

在闭包中,变量和方法对执行器必须是可见的,才能序列化后传输给每个executor。如果是在集群模式下,每个executor都会有一分驱动程序中变量的拷贝,这个时候其他executor中的变量除了自己那份拷贝外再也看不到其他拷贝做了什么了,于是一个简单的累加都可能因为每个executor的不同而失败。如果是本地模式,因为驱动程序中的变量独此一份,也就可能计算成功。

这个有点线程中的同步的意思。为了使得多线程同步,需要让所有操作对所有线程可见。

于是就有了 Accumulator等方法。

>>> accum = sc.accumulator(0)
>>> accum
Accumulator<id=0, value=0>

>>> sc.parallelize([1, 2, 3, 4]).foreach(lambda x: accum.add(x))
...
10/09/29 18:41:08 INFO SparkContext: Tasks finished in 0.317106 s

>>> accum.value
10

或者是
class VectorAccumulatorParam(AccumulatorParam):
    def zero(self, initialValue):
        return Vector.zeros(initialValue.size)

    def addInPlace(self, v1, v2):
        v1 += v2
        return v1

# Then, create an Accumulator of this type:
vecAccum = sc.accumulator(Vector(...), VectorAccumulatorParam())

六、shuffle操作

shuffle操作:

在计算单个任务只会在单个划分的数据中进行,所以为了让所有的数据都能够得到计算,需要把所有的数据集中所有的key以及对应的value聚集在一起,形成针对每个key跨节点计算。

可想而知,这个操作对于磁盘I/O、数据序列化和网络I/O的压力是十分巨大的,因此需要map去组织数据,reduce聚合数据,这里面的map和reduce是由MapReduce来的概念而不是操作。

这个操作对堆内存的消耗是非常明显的,因为大量的任务计算后的结果被保存在内存中,同时还会产生大量的临时文件在磁盘中直至不再需要。

七、RDD persist

在操作的过程中,将数据集保存在内存中,反复利用去进行其他的action,方法是persist() or cache() 。最后,这些结果也可以在不同级别的存储体系中存储。

Spark also automatically persists some intermediate data in shuffle operations (e.g. reduceByKey), even without users calling persist. This is done to avoid recomputing the entire input if a node fails during the shuffle. We still recommend users call persist on the resulting RDD if they plan to reuse it.

一般情况下,如果内存足够,选择默认的(MEMORY_ONLY),因为这就是最高效的模式;

除非万不得已,数据集实在太大不要选择磁盘。因为这样计算时间几乎和数据输入时间不相上下了。

八、共享变量

broadcast variables:

在集群中的每个机器中保存一个只读变量,避免了在任务之间进行复制流动。

解决了闭包函数引用外部大变量引起的性能问题

如果有个较大的数据集输入的话,广播可以相对高效地将数据集推送到所有节点。广播之后的对象仍然要确保每个节点都一样。

>>> broadcastVar = sc.broadcast([1, 2, 3])
<pyspark.broadcast.Broadcast object at 0x102789f10>

>>> broadcastVar.value
[1, 2, 3]

Accumulators之前介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
About This Book, Learn why and how you can efficiently use Python to process data and build machine learning models in Apache Spark 2.0Develop and deploy efficient, scalable real-time Spark solutionsTake your understanding of using Spark with Python to the next level with this jump start guide, Who This Book Is For, If you are a Python developer who wants to learn about the Apache Spark 2.0 ecosystem, this book is for you. A firm understanding of Python is expected to get the best out of the book. Familiarity with Spark would be useful, but is not mandatory., What You Will Learn, Learn about Apache Spark and the Spark 2.0 architectureBuild and interact with Spark DataFrames using Spark SQLLearn how to solve graph and deep learning problems using GraphFrames and TensorFrames respectivelyRead, transform, and understand data and use it to train machine learning modelsBuild machine learning models with MLlib and MLLearn how to submit your applications programmatically using spark-submitDeploy locally built applications to a cluster, In Detail, Apache Spark is an open source framework for efficient cluster computing with a strong interface for data parallelism and fault tolerance. This book will show you how to leverage the power of Python and put it to use in the Spark ecosystem. You will start by getting a firm understanding of the Spark 2.0 architecture and how to set up a Python environment for Spark., You will get familiar with the modules available in PySpark. You will learn how to abstract data with RDDs and DataFrames and understand the streaming capabilities of PySpark. Also, you will get a thorough overview of machine learning capabilities of PySpark using ML and MLlib, graph processing using GraphFrames, and polyglot persistence using Blaze. Finally, you will learn how to deploy your applications to the cloud using the spark-submit command., By the end of this book, you will have established a firm understanding of the Spark Python API and how it can be used t

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值