弹性分布式数据集(Resilient Distributed Dataset,简称RDD),分布式的元素集合。
3.1 RDD基础
-
创建RDD:
1)读取一个外部数据集
2)在驱动器程序里分发驱动器程序中的对象集合(list和set) -
RDD支持的操作类型
1)转化操作(transformation):一个RDD生成一个新的RDD
2)行动操作(action):计算出结果,返回到驱动器程序中,或存储到外部存储系统
Spark只有第一次在一个行动操作中用到时,才会真正计算RDD,惰性计算。
如果想在多个行动操作中重用同一个RDD,可以使用RDD.persist()让Spark把这个RDD缓存下来。
3.2 RDD
1)读取外部数据集
2)在驱动器程序中对一个集合进行并行化
把一个已有集合传给SparkContext的parallelize()简单创建RDD。
3.3 RDD操作
3.3.1 转化操作
>>> inputRDD = sc.textFile('E:\spark\log.txt')
>>> errorsRDD = inputRDD.filter(lambda x: "error" in x)
>>> errorsRDD.first()
[Stage 0:> (0 + 1) / 1]
'error:'
>>>
3.3.2 行动操作
用count()来返回计数结果
用take()来收集RDD中的一些元素
collect()用来获取整个RDD中的数据
saveAsTextFile()、saveAsSequenceFile()把RDD的数据内容保存起来。
3.3.3 惰性求值
RDD的转化操作都是惰性求值的。
3.4 向Spark传递函数
3.4.1 Python
1)lambda表达式
>>> errorsRDD.filter(lambda s: "error" in s)
2)传递顶层函数或是定义的局部函数
3.4.2 Scala
3.4.3 Java
1)使用具名类进行函数传递
2)使用匿名内部类进行函数传递
3)lambda表达式
3.5 常见的转化操作和行动操作
3.5.1 基本RDD
- 针对各个元素的转化操作
map()和filter()
>>> nums = sc.parallelize([1,2,3,4])
>>> squared = nums.map(lambda x : x * x).collect()
[Stage 4:> (0 + 4) / 4]
>>> for num in squared:
... print("%i",num)
...
%i 1
%i 4
%i 9
%i 16
>>>
flatMap(): 对每个输入元素生成多个输出元素。
>>> lines = sc.parallelize(["hello world","hi"])
>>> words = lines.map(lambda line:line.split(" ")).collect()
[Stage 5:> (0 + 4) / 4]
>>> print(words)
[['hello', 'world'], ['hi']]
>>> words2 = lines.flatMap(lambda line : line.split(" ")).collect()
[Stage 6:> (0 + 4) / 4]
>>> print(words2)
['hello', 'world', 'hi']
>>>
- 伪集合操作
-
distinct()
使用RDD.distinct()转化操作来生成一个只包含不同元素的新的RDD。 -
union()
返回一个包含两个RDD中所有元素的RDD -
intersection()
只返回两个RDD中都有的元素 -
subtract()
返回只存在于第一个RDD中而不存在于第二个RDD中的所有元素组成的RDD。 -
cartesian()
笛卡尔积
3.行动操作
- reduce(),fold()(加初始值)
操作两个RDD的元素类型的数据并返回一个同样类型的新元素。
>>> nums = sc.parallelize([1,2,3,4])
>>> print(nums)
ParallelCollectionRDD[0] at parallelize at PythonRDD.scala:184
>>> sum = nums.reduce(lambda x,y : x + y)
[Stage 0:> (0 + 4) / 4]
>>> print(sum)
10
>>>
- aggregate()
返回值类型可以和RDD类型不同。
>>> nums = sc.parallelize([1,2,3,4,5])
>>> sumCount = nums.aggregate((0,0),(lambda acc,value:(acc[0] + value,acc[1] + 1
)),(lambda acc1,acc2:(acc1[0] + acc2[0],acc1[1] + acc2[1])))
[Stage 1:> (0 + 4) / 4]
>>> print(sumCount[0]/float(sumCount[1]))
3.0
>>>
3.5.2 在不同RDD类型间转换
-
Scala
-
Java
1)JavaDoubleRDD
2)JavaPairRDD
创建特殊类型的RDD:
1)使用特殊版本的Function
2)调用RDD上别的函数(mapToDouble()代替map())
- Python
所有函数都实现在基本的RDD类中。
3.6 持久化(缓存)
-
persist()
为避免多次计算同一个RDD,可以让Spark对数据进行持久化。
把数据以序列化的形式缓存在JVM的堆空间中。 -
unpersist()
手动把持久化的RDD从缓存中移除
3.7 总结