一、RDD概述
1、 RDD是最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合,具有数据流模型的特点:自动容错,位置感知性调度和可伸缩性,允许用户在执行多个查询时显式的将工作集缓存在内存中,后续的查询能够重用工作集,提升了查询速度。
2、RDD属性:
- 一组分片,数据集的基本组成单位,用户可以创建RDD时指定RDD的分片个数,如果没有指定,就会采取默认值
- 一个计算每个分区的函数,spark的计算是以分片为单位的,每个RDD都会实现计算函数以达到这个目的,而compute函数会对迭代器进行复核,不需要保存每次计算的结果
- 依赖关系:RDD每次转换都会生成新的RDD,这种流水线式的依赖关系,在部分数据丢失后,可以根据依赖关系重新计算丢失的分区数据,而不是对所有分区进行重新计算。
- Partitoner:分片函数:HashPartitioner,RangePartitioner,只有对于key-value的RDD,才会有Partitioner,非Key-Value的RDD的Partitioner的值是None,分片函数决定了分片的数量以及 父RDD shuffle输出时的分片数量
- 存储存取每个Partition的优先位置,对于一个HDFS文件来说,这个列表保存的就是每个partiton所在块的位置,移动数据不如移动计算,spark在 任务调度的时候,会尽可能的将计算任务分配到其所要处理数据块的存储位置。
3、RDD特性
- 只读:不能修改,只能通过转换操作生成新的 RDD。
- 分布式:可以分布在多台机器上进行并行处理。
- 弹性:计算过程中内存不够时它会和磁盘进行数据交换。
- 基于内存:可以全部或部分缓存在内存中,在多次计算间重用。
二、RDD基本操作
---大佬总结文章链接:
1、Transformation
Transformation用于对RDD的创建,RDD只能使用Transformation创建,同时还提供大量操作方法,包括map,filter,groupBy,join等,RDD利用这些操作生成新的RDD,但是需要注意,无论多少次Transformation,在RDD中真正数据计算Action之前都不可能真正运行。
2、Action
Action是数据执行部分,其通过执行count,reduce,collect等方法真正执行数据的计算部分。实际上,RDD中所有的操作都是Lazy模式进行,运行在编译中不会立即计算最终结果,而是记住所有操作步骤和方法,只有显示的遇到启动命令才执行。这样做的好处在于大部分前期工作在Transformation时已经完成,当Action工作时,只需要利用全部自由完成业务的核心工作。
3、下面是在python中对RDD的生成,以及一些基本的Transformation,Action操作。
from pyspark import SparkContext, SparkConf
from pyspark.streaming import StreamingContext
import math
appName ="jhl_spark_1" #你的应用程序名称
master= "local"#设置单机
conf = SparkConf().setAppName(appName).setMaster(master)#配置SparkContext
sc = SparkContext(conf=conf)
# parallelize:并行化数据,转化为RDD
data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data, numSlices=10) # numSlices为分块数目,根据集群数进行分块
# textFile读取外部数据
rdd = sc.textFile("./c2.txt") # 以行为单位读取外部文件,并转化为RDD
print rdd.collect()
# map:迭代,对数据集中数据进行单独操作
def my_add(l):
return (l,l)
data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data) # 并行化数据集
result = distData.map(my_add)
print (result.collect()) # 返回一个分布数据集
# filter:过滤数据
def my_add(l):
result = False
if l > 2:
result = True
return result
data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data)#并行化数据集,分片
result = distData.filter(my_add)
print (result.collect())#返回一个分布数据集
# zip:将两个RDD对应元素组合为元组
x = sc.parallelize(range(0,5))
y = sc.parallelize(range(1000, 1005))
print x.zip(y).collect()
#union 组合两个RDD
print x.union(x).collect()
# Aciton操作
# collect:返回RDD中的数据
rdd = sc.parallelize(range(1, 10))
print rdd
print rdd.collect()
# collectAsMap:以rdd元素为元组,以元组中一个元素作为索引返回RDD中的数据
m = sc.parallelize([('a', 2), (3, 4)]).collectAsMap()
print m['a']
print m[3]
# groupby函数:根据提供的方法为RDD分组:
rdd = sc.parallelize([1, 1, 2, 3, 5, 8])
def fun(i):
return i % 2
result = rdd.groupBy(fun).collect()
print [(x, sorted(y)) for (x, y) in result]
# reduce:对数据集进行运算
rdd = sc.parallelize(range(1, 10))
result = rdd.reduce(lambda a, b: a + b)
print result
map() # 将函数应用于 RDD 中的每个元素,将返回值构成新的 RDD
rdd.map(x => x + 1) {2, 3, 4, 4}
flatMap() # 将函数应用于 RDD 中的每个元素,将返回的迭代器的所有内容构成新的 RDD。通常用来切
分单词
rdd.flatMap(x => x.to(3)) {1, 2, 3, 2, 3, 3, 3}
filter() # 返回一个由通过传给 filter()的函数的元素组成的 RDD
rdd.filter(x => x != 1) {2, 3, 3}
distinct() # 去重 rdd.distinct() {1, 2, 3}
sample(withRe
placement, fra
ction, [seed])
union() # 生成一个包含两个 RDD 中所有元素的 RDD
rdd.union(other) # {1, 2, 3, 3, 4, 5}
intersection() # 求两个 RDD 共同的元素的 RDD rdd.intersection(other) {3}
subtract() # 移除一个 RDD 中的内容(例如移除训练数据)
rdd.subtract(other) # {1, 2}
cartesian() # 与另一个 RDD 的笛卡儿积 rdd.cartesian(other) {(1, 3), (1, 4), ...
(3, 5)}
collect() # 返回 RDD 中的所有元素 rdd.collect() {1, 2, 3, 3}
count() # RDD 中的元素个数 rdd.count() 4
countByValue() # 各元素在 RDD 中出现的次数 rdd.countByValue() {(1, 1),
(2, 1),
(3, 2)}
take(num) # 从 RDD 中返回 num 个元素 rdd.take(2) {1, 2}
top(num) # 从 RDD 中返回最前面的 num个元素
rdd.top(2) # {3, 3}
takeOrdered(num)
(ordering)
# 从 RDD 中按照提供的顺序返回最前面的 num 个元素
rdd.takeOrdered(2)(myOrdering) # {3, 3}
takeSample(withReplace
ment, num, [seed])
# 从 RDD 中返回任意一些元素 rdd.takeSample(false, 1) 非确定的reduce(func) 并 行 整 合 RDD 中 所 有 数 据(例如 sum)
rdd.reduce((x, y) => x + y) 9
fold(zero)(func) # 和 reduce() 一 样, 但 是 需 要提供初始值
rdd.fold(0)((x, y) => x + y) 9
aggregate(zeroValue)
(seqOp, combOp)
# 和 reduce() 相 似, 但 是 通 常返回不同类型的函数
rdd.aggregate((0, 0))
((x, y) =>
(x._1 + y, x._2 + 1),
(x, y) =>
(x._1 + y._1, x._2 + y._2))
(9,4)
foreach(func) # 对 RDD 中的每个元素使用给定的函数
rdd.foreach(func)