RDD简介:
spark中的rdd就是一个不可变的分布式对象集合。每个rdd都被分为多个分区,这些分区运行在集群中不同的节点上。rdd可以包含python,java,scala中任意类型的对象,甚至可以包含用户自定义对象。
RDD支持两种类型的操作:一是转化操作,一个是行动操作,转化操作返回的是RDD, 行动操作返回的是其他类型。
创建RDD:
创建RDD最简单的方式是吧程序中一个已有的集合传给SparkContext的paralleize()方法,这种方式在学习spark时非常有用,可以快速创建rdd,然后对其进行操作,代码如下
启动pyspark(见上一篇)输入:
lines = sc.parallelize(["hello girl", "it's me"])
如上代码是用python形式在内存中创建了一个名为lines的rdd,开发时这种方式运用的并不多,因为这样把整个数据集先放到了一台机器的内存中了。
更常用的方式是从外部存储中读取数据来创建RDD,比如从一个文本文件来创建存储字符串的rdd, 代码如下:
lines = sc.textFile("/path/to/README.md")
如上代码是创建了一个名为lines的rdd,其中存储的是文件README.md中的内容。
这里的sc是SparkContext对象,在交互式操作时,shell启动时已经自动创建了SparkContext对象,也就是这里的sc,而在独立的python或java应用中,我们要手动创建SparkContext对象,如下代码演示:
python:
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local").setAppName("MyApp")
sc = SparkContext(conf = conf)
java:
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
SparkConf conf = new SparkConf().setMaster("local").setAppName("MyApp");
JavaSparkContext sc = new JavaSparkContext(conf);
RDD操作:
3.1 转化操作:转化操作不改变原有的rdd数据,返回一个新的rdd
比如:resultRdd = lines.filter(lambda x: "spark" in x)
这句代码创建了一个名为resultRdd的新RDD对象,里面存储的是在lines中包含单词“spark”的所有行
我们还可以用union来合并两个rdd形成一个新的rdd,比如:rdd1 = rdd2.union(rdd3)
另外一个常用操作时map操作,map是对rdd里的每个元素进行规定的操作,比如:
num = sc.parallelize([1,2,3,4])
squared = num.map(lambda x: x*x)
如上代码先创建了一个存储了四个整数的rdd,接着用map创建了一个存储了num里面每个数的平方的rdd,也就是[1,4,9,16]
3.2 行动操作:行动操作会把计算结果返回给驱动程序
比如 lines.count() 返回rdd中的元素个数,lines.first()返回rdd中的第一个元素,需要注意的是rdd是惰性求值的,也就是在行动操作之前spark不会开始操作。
向Spark传递函数:
spark的大部分转化操作和一部分行动操作,都依赖用户传递的函数来计算。下面是python的传递方式:
def containsError(s):
return "error" in s
word = rdd.filter(containErrors)
需要注意当你传递的对象是某个对象的成员,或者包含了对某个对象中一个字段的引用时,spark会把整个对象发到工作节点上,这会导致传递比你预期大得多的信息。可以把需要的字段从对象中提出来放到一个局部变量中,然后传递局部变量。
常见的转化操作和行动操作:
转化操作:
map() 将函数应用于rdd中的每个元素,将返回值构成新的rdd
flatMap() 将函数应用于rdd中的每个元素,将返回的迭代器的所有内容构成新的rdd
filter() 返回一个由通过传给filter()的函数的元素组成的rdd
distinct() 去重
union 生成一个包含两个rdd中所有元素的新的rdd
intersection() 生成一个新的rdd存储两个rdd的交集
subtract() 生成一个新的rdd存储两个rdd的差集
cartesian() 生成一个新的rdd 存储两个rdd的笛卡尔积
行动操作:
reduce(): 接收一个函数作为参数,这个函数接收两个相同元素类型的rdd数据并返回一个同样类型的新元素。比如用reduce求和。
sum = nums.reduce(lambda x,y: x+y) 求出nums中所有元素的和。
此外还有fold和aggregate,以后细说。
持久化:
Spark RDD是惰性求值的,当我们多次使用同一个rdd的时候,spark每次都会重算该rdd以及它所有的依赖,这在迭代算法中消耗格外大,所以这时候我们需要对数据进行持久化。在python中,持久化默认级别是以序列化后的对象存储在jvm堆空间中。
持久化的方法是persist(),比如,这样只计算一次squared,参数是持久化级别
squared.persist(StorageLevel.DISK_ONLY)
squared.count()
squared.first()
转载于:https://my.oschina.net/u/2609444/blog/618839