rdd分片 spark_Python版的Spark编程指导!神级程序员强推!你得花半小时阅读!

根据下面原文和网上的译文结合自己的实际需要整理一下,当做笔记和回查!在给大家分享之前呢,小编推荐一下一个挺不错的交流宝地,里面都是一群热爱并在学习Python的小伙伴们,大几千了吧,各种各样的人群都有,特别喜欢看到这种大家一起交流解决难题的氛围,群资料也上传了好多,各种大牛解决小白的问题,这个Python群:330637182 欢迎大家进来一起交流讨论,一起进步,尽早掌握这门Python语言。

概述

从高层次上来看,每一个Spark应用都包含一个驱动程序,用于执行用户的main函数以及在集群上运行各种并行操作。 Spark提供的主要抽象是弹性分布式数据集( RDD ),这是一个包含诸多元素、被划分到不同节点上进行并行处理的数据集合。 RDD通过打开HDFS(或其他hadoop支持的文件系统)上的一个文件、在驱动程序中打开一个已有的Scala集合或由其他 RDD转换操作得到。 用户可以要求Spark将RDD持久化到内存中,这样就可以有效地在并行操作中复用。另外,在节点发生错误时RDD可以自动恢复。

Spark提供的 另一个抽象是可以在并行操作中使用的共享变量 。在默认情况下,当Spark将一个函数转化成许多任务在不同的节点上运行的时候,对于所有在函数中使用的变量,每一个任务都会得到一个副本。有时,某一个变量需要在任务之间或任务与驱动程序之间共享。Spark支持两种共享变量: 广播变量 ,用来将一个值缓存到所有节点的内存中; 累加器 ,只能用于累加,比如计数器和求和。

连接Spark

Spark1.3.0只支持Python2.6或更高的版本(但不支持Python3), 但是Spark2.0.0支持 。它使用了标准的CPython解释器,所以诸如NumPy一类的C库也是可以使用的。

通过Spark目录下的 bin/spark-submit 脚本你可以在Python中运行Spark应用。这个脚本会载入Spark的Java/Scala库然后让你将应用提交到集群中。 你可以执行 bin/pyspark 来打开Python的交互命令行。

如果你希望访问HDFS上的数据,你需要为你使用的HDFS版本建立一个PySpark连接。常见的HDFS版本标签都已经列在了这个第三方发行版页面。

最后,你需要将一些Spark的类import到你的程序中。加入如下这行:

from pyspark import SparkContext, SparkConf

想要了解命令行选项的完整信息请执行 pyspark --help命令。在这些场景下,pyspark会触发一个更通用的spark-submit脚本

并行集合的 一个重要参数是将数据集划分成分片的数量 。对每一个分片,Spark会在集群中运行一个对应的任务。典型情况下,集群中的每一个CPU将对应运行2-4个分片。一般情况下,Spark会根据当前集群的情况自行设定分片数量。但是, 你也可以通过将第二个参数传递给parallelize方法(比如 sc.parallelize(data, 10) )来手动确定分片数量 。注意:有些代码中会使用切片(slice,分片的同义词)这个术语来保持向下兼容性。

外部数据集

PySpark可以通过Hadoop支持的外部数据源(包括本地文件系统、HDFS、 Cassandra、HBase、亚马逊S3等等)建立分布数据集。Spark支持文本文件、 序列文件 以及其他任何 Hadoop输入格式文件 。

通过文本文件创建RDD要使用SparkContext的textFile方法。这个方法会使用一个文件的URI(或本地文件路径,hdfs://、s3n://这样的URI等等)然后读入这个文件建立一个文本行的集合。以下是一个例子:

distFile = sc.textFile('data.txt')

建立完成后distFile上就可以调用数据集操作了。比如,我们可以调用map和reduce操作来叠加所有文本行的长度,代码如下:

distFile.map(lambda s: len(s)).reduce(lambda a, b: a + b)

在Spark中读入文件时有几点要注意:如果使用了本地文件路径时,要保证在worker节点上这个文件也能够通过这个路径访问。这点可以通过将这个文件拷贝到所有worker上或者使用网络挂载的共享文件系统来解决。

包括textFile在内的所有基于文件的Spark读入方法,都支持将文件夹、压缩文件、包含通配符的路径作为参数。比如,以下代码都是合法的:

可写类型支持

PySpark序列文件支持利用Java作为中介载入一个键值对RDD,将可写类型转化成Java的基本类型,然后使用Pyrolite将java结果对象串行化。当将一个键值对RDD储存到一个序列文件中时PySpark将会运行上述过程的相反过程。首先将Python对象反串行化成Java对象,然后转化成可写类型。以下可写类型会自动转换:

可写类型Python类型Textunicode str

IntWritableint

FloatWritablefloat

DoubleWritablefloat

BooleanWritablebool

BytesWritablebytearray

NullWritableNone

MapWritabledict

数组是不能自动转换的。用户需要在读写时指定ArrayWritable的子类型.在读入的时候,默认的转换器会把自定义的ArrayWritable子类型转化成Java的Object[],之后串行化成Python的元组。为了获得Python的array.array类型来使用主要类型的数组,用户需要自行指定转换器。

保存和读取序列文件

和文本文件类似,序列文件可以通过指定路径来保存与读取。键值类型都可以自行指定,但是对于标准可写类型可以不指定。

RDD操作

RDD支持两类操作: 转化操作 ,用于从已有的数据集转化产生新的数据集; 启动操作 ,用于在计算结束后向驱动程序返回结果。举个例子,map是一个转化操作,可以将数据集中每一个元素传给一个函数,同时将计算结果作为一个新的RDD返回。另一方面,reduce操作是一个启动操作,能够使用某些函数来聚集计算RDD中所有的元素,并且向驱动程序返回最终结果(同时还有一个并行的reduceByKey操作可以返回一个分布数据集)。

在Spark所有的转化操作都是 惰性求值 的,就是说它们并不会立刻真的计算出结果。相反,它们仅仅是记录下了转换操作的操作对象(比如:一个文件)。只有当一个启动操作被执行,要向驱动程序返回结果时,转化操作才会真的开始计算。这样的设计使得Spark运行更加高效——比如,我们会发觉由map操作产生的数据集将会在reduce操作中用到,之后仅仅是返回了reduce的最终的结果而不是map产生的庞大数据集。

在默认情况下,每一个由转化操作得到的RDD都会在每次执行启动操作时重新计算生成。但是,你也可以通过调用persist(或cache)方法来将RDD 持久化 到内存中,这样Spark就可以在下次使用这个数据集时快速获得。Spark同样提供了对将RDD持久化到硬盘上或在多个节点间复制的支持。

比如,传递一个无法转化为 lambda表达式长函数,可以像以下代码这样:

转化操作

转化操作作用map(func)返回一个新的分布数据集,由原数据集元素经func处理后的结果组成

filter(func)返回一个新的数据集,由传给func返回True的原数据集元素组成

flatMap(func)与map类似,但是每个传入元素可能有0或多个返回值,func可以返回一个序列而不是一个值

mapParitions(func)类似map,但是RDD的每个分片都会分开独立运行,所以func的参数和返回值必须都是迭代器

mapParitionsWithIndex(func)类似mapParitions,但是func有两个参数,第一个是分片的序号,第二个是迭代器。返回值还是迭代器

sample(withReplacement, fraction, seed)使用提供的随机数种子取样,然后替换或不替换

union(otherDataset)返回新的数据集,包括原数据集和参数数据集的所有元素

intersection(otherDataset)返回新数据集,是两个集的交集

distinct([numTasks])返回新的集,包括原集中的不重复元素

groupByKey([numTasks])当用于键值对RDD时返回(键,值迭代器)对的数据集

aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])用于键值对RDD时返回(K,U)对集,对每一个Key的value进行聚集计算

sortByKey([ascending], [numTasks])用于键值对RDD时会返回RDD按键的顺序排序,升降序由第一个参数决定

join(otherDataset, [numTasks])用于键值对(K, V)和(K, W)RDD时返回(K, (V, W))对RDD

cogroup(otherDataset, [numTasks])用于两个键值对RDD时返回(K, (V迭代器, W迭代器))RDD

cartesian(otherDataset)用于T和U类型RDD时返回(T, U)对类型键值对RDD

pipe(command, [envVars])通过shell命令管道处理每个RDD分片

coalesce(numPartitions)把RDD的分片数量降低到参数大小

repartition(numPartitions)重新打乱RDD中元素顺序并重新分片,数量由参数决定

repartitionAndSortWithinPartitions(partitioner)按照参数给定的分片器重新分片,同时每个分片内部按照键排序

下面的表格列出了Spark支持的常用转化操作。欲知细节,请查阅RDD API文档(Scala, Java, Python)和键值对RDD函数文档(Scala, Java)。

(译者注:这部分翻译比较简略,仅供简单参考,具体细节请看文档)

转化操作作用map(func)返回一个新的分布数据集,由原数据集元素经func处理后的结果组成

filter(func)返回一个新的数据集,由传给func返回True的原数据集元素组成

flatMap(func)与map类似,但是每个传入元素可能有0或多个返回值,func可以返回一个序列而不是一个值

mapParitions(func)类似map,但是RDD的每个分片都会分开独立运行,所以func的参数和返回值必须都是迭代器

mapParitionsWithIndex(func)类似mapParitions,但是func有两个参数,第一个是分片的序号,第二个是迭代器。返回值还是迭代器

sample(withReplacement, fraction, seed)使用提供的随机数种子取样,然后替换或不替换

union(otherDataset)返回新的数据集,包括原数据集和参数数据集的所有元素

intersection(otherDataset)返回新数据集,是两个集的交集

distinct([numTasks])返回新的集,包括原集中的不重复元素

groupByKey([numTasks])当用于键值对RDD时返回(键,值迭代器)对的数据集

aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])用于键值对RDD时返回(K,U)对集,对每一个Key的value进行聚集计算

sortByKey([ascending], [numTasks])用于键值对RDD时会返回RDD按键的顺序排序,升降序由第一个参数决定

join(otherDataset, [numTasks])用于键值对(K, V)和(K, W)RDD时返回(K, (V, W))对RDD

cogroup(otherDataset, [numTasks])用于两个键值对RDD时返回(K, (V迭代器, W迭代器))RDD

cartesian(otherDataset)用于T和U类型RDD时返回(T, U)对类型键值对RDD

pipe(command, [envVars])通过shell命令管道处理每个RDD分片

coalesce(numPartitions)把RDD的分片数量降低到参数大小

repartition(numPartitions)重新打乱RDD中元素顺序并重新分片,数量由参数决定

repartitionAndSortWithinPartitions(partitioner)按照参数给定的分片器重新分片,同时每个分片内部按照键排序

启动操作

下面的表格列出了Spark支持的部分常用启动操作。欲知细节,请查阅RDD API文档(Scala, Java, Python)和键值对RDD函数文档(Scala, Java)。

(译者注:这部分翻译比较简略,仅供简单参考,具体细节请看文档)

启动操作作用reduce(func)使用func进行聚集计算,func的参数是两个,返回值一个,两次func运行应当是完全解耦的,这样才能正确地并行运算

collect()向驱动程序返回数据集的元素组成的数组

count()返回数据集元素的数量

first()返回数据集的第一个元素

take(n)返回前n个元素组成的数组

takeSample(withReplacement, num, [seed])返回一个由原数据集中任意num个元素的suzuki,并且替换之

takeOrder(n, [ordering])返回排序后的前n个元素

saveAsTextFile(path)将数据集的元素写成文本文件

saveAsSequenceFile(path)将数据集的元素写成序列文件,这个API只能用于Java和Scala程序

saveAsObjectFile(path)将数据集的元素使用Java的序列化特性写到文件中,这个API只能用于Java和Scala程序

countByCount()只能用于键值对RDD,返回一个(K, int) hashmap,返回每个key的出现次数

foreach(func)对数据集的每个元素执行func, 通常用于完成一些带有副作用的函数,比如更新累加器(见下文)或与外部存储交互等

RDD持久化

Spark的一个重要功能就是在将数据集 持久化 (或 缓存 )到内存中以便在多个操作中重复使用。当我们持久化一个RDD是,每一个节点将这个RDD的每一个分片计算并保存到内存中以便在下次对这个数据集(或者这个数据集衍生的数据集)的计算中可以复用。这使得接下来的计算过程速度能够加快(经常能加快超过十倍的速度)。缓存是加快迭代算法和快速交互过程速度的关键工具。

删除数据

Spark会自动监视每个节点的缓存使用同时使用LRU算法丢弃旧数据分片。如果你想手动删除某个RDD而不是等待它被自动删除,调用 RDD.unpersist()方法。

共享变量

通常情况下,当一个函数传递给一个在远程集群节点上运行的Spark操作(比如map和reduce)时,Spark会对涉及到的变量的所有副本执行这个函数。这些变量会被复制到每个机器上,而且这个过程不会被反馈给驱动程序。通常情况下,在任务之间读写共享变量是很低效的。但是,Spark仍然提供了有限的两种共享变量类型用于常见的使用场景:广播变量和累加器。

广播变量

广播变量允许程序员在每台机器上保持一个只读变量的缓存而不是将一个变量的拷贝传递给各个任务。它们可以被使用,比如,给每一个节点传递一份大输入数据集的拷贝是很低效的。Spark试图使用高效的广播算法来分布广播变量,以此来降低通信花销。

其他

集群部署

这个 应用提交指南 描述了一个应用被提交到集群上的过程。简而言之,只要你把你的应用打成了JAR包(Java/Scala应用)或.py文件的集合或.zip压缩包(Python应用),bin/spark-submit脚本会将应用提交到任意支持的集群管理器上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值