Spark RDD基础(一)

来源:互联网 发布:出租女友网站源码 编辑:程序博客网 时间:2024/05/15 05:07

spark对数据的核心抽象—弹性分布式数据集(Resilient Distributed Dataset)即RDD,RDD是一个不可变的分布式对象集合,每个RDD被分为多个分区。
在spark中,对数据的所有操作不外乎创建RDD,转化已有RDD以及调用RDD操作进行求值

RDD基础

#创建RDDlines=sc.textFile("README.md")#转化操作由一个RDD生成一个新的RDD#返回一个只存储包含python字符串的新RDDpythonLines=lines.filter(lambda line:"Python" in line)#行动操作pythonLines.first()

转化操作和行动操作的区别在于spark计算RDD的方式不用。spark只有第一次在一个行动操作中用到时才会真正的计算。比如对于上面的例子,spark在运行

lines=sc.textFile("README.md")

时候并不会立刻读取文件并存储,而是当spark了解整个操作链后,只计算真正要用的数据,对于这个例子spark在行动操作first()中,spark只需要扫描文件直到找到第一个匹配的行为止,而不需要读取整个文件。

在实际操作中我们经常使用persist把数据读取到内存中,并反复查询这部分数据。比如,如果我们想多次对README文件中包含python的行进行计算,可以写如下的脚本

#将RDD持久化到内存中pythonLines.persistpythonLines.count()pythonLines.first()

每个spark程序无外乎都是下面的流程

1.从外部数据创建输入RDD
2.使用诸如filter()这样的操作对RDD进行转化,定义新的RDD
3.告诉spark对需要被重用的中间RDD执行persisit()操作
4.使用行动操作(count(),first())触发一次并行计算,spark并不会立马执行,而是优化后再执行

创建RDD

#parallelize方法将集合转化为rddlines = sc.parallelize(["pandas", "i like pandas"])#textFile方法lines=sc.textFile("README.md")

RDD操作

spark支持两种操作转化操作,行动操作

转化操作
转化操作执行时返回新的RDD的操作,转化出来的RDD是惰性求值的,只有在行动中用到这些RDD时才会被计算,许多转化操作只会操作RDD中的一个元素,并不是所有的转化操作都是这样

比如提取日志文件的错误信息

inputRDD=sc.testFile("log.txt")errorsRDD=inputRDD.filter(lambda x:"error" in x)warningsRDD = inputRDD.filter(lambda x: "warning" in x)badLinesRDD = errorsRDD.union(warningsRDD)

通过转化操作,从已有的RDD中派生新的RDD,spark会使用谱系图记录这些RDD的依赖关系,spark在需要用这些信息的时候按需计算每个RDD,也可以依靠谱系图在丢失数据的情况下恢复丢失的数据

行动操作
行动操作需要实际的输出,它会强制执行哪些求值必须用到的RDD转化操作
示例:对badLinesRDD进行计数操作,并且打印前十条记录

print "Input had " + badLinesRDD.count() + " concerning lines"for line in badLinesRDD.take(10):    print line

这里使用了take()取出少量的数据集,也可以使用collect()函数获取整个RDD中的数据,但是使用collect需要注意内存是否够用。如果数据集特别大的时候,我们需要把数据写到诸如HDFS之类的分布式存储系统,当调用一个新的行动操作的时候整个RDD会从头计算,我们要将中间结果持久化

惰性求值

spark类似sc.textFile()或者转化操作都是惰性的,可以使用一个行动操作来强制spark执行RDD转化操作

函数传递

#使用lambda方法传递word = rdd.filter(lambda s: "error" in s)#定义一个函数然后传递def containsError(s):    return "error" in sword = rdd.filter(containsError)

传递函数时要小心,python会在不经意间把函数所在的对象也序列化传出,有时如果传递的类里包含了python不知道如何序列化输出的对象,也可能导致程序失败。

如下是一个错误的函数传递示例

class SearchFunctions(object):    def __init__(self, query):        self.query = query    def isMatch(self, s):        return self.query in s    def getMatchesFunctionReference(self, rdd):        # 问题:在"self.isMatch"中引用了整个self        return rdd.filter(self.isMatch)    def getMatchesMemberReference(self, rdd):        # 问题:在"self.query"中引用了整个self        return rdd.filter(lambda x: self.query in x)

对于上述的方法替代方案如下

class WordFunctions(object):    def getMatchesNoReference(self, rdd):        # 安全:只把需要的字段提取到局部变量中        query = self.query        return rdd.filter(lambda x: query in x)
                                            spark快速大数据分析学习笔记
原创粉丝点击