RDD(弹性分布式数据集)
RDD即弹性分布式数据集,有容错机制并可以被并行操作的元素集合,具有只读、可分区、容错、高效、无需物化、可以缓存、RDD依赖等特征。RDD只是数据集的抽象,分区内部并不会存储具体的数据。存储的只是具体数据的分区信息getPartitions,还有就是针对单个分区的读取方法compute。RDD的数据默认情况下存放在内存中,但是在内存资源不足时,spark会自动将RDD数据写入磁盘中。
1 创建RDD
Spark提供了两种创建RDD的方式:读取外部数据集,以及在程序中对一个集合进行并行化。
①将一个已有的集合传给SparkContext的parallelize()方法,如:
JavaRDD<String> lines = sc. parallelize(Arrays.asList(“pandas”, ”I like pandas”));
②从外部存储中读取数据来创建RDD,如:
JavaRDD<String> lines = sc.textFile(“/path/to/README.md”);
2 RDD操作
RDD支持两种操作:转化操作和行动操作。RDD的转化操作是返回一个新的RDD的操作,比如map()和filter(),而行动操作则是向程序返回结果或把结果写入外部系统的操作,会触发实际的计算,比如count()和first()。
RDD的转化操作都是惰性求值的,这意味着在被调用行动操作之前Spark不会开始计算。Spark会在内部记录下所有要求执行的操作的相关信息。这样Spark就可以把一些操作合并到一起来减少计算数据的步骤,用户可以用更小的操作来组织他们的程序。
Spark的大部分转化操作和一部分行动操作,都需要依赖用户传递的函数来计算。在Java中根据不同的返回类型,定义了一些不同的接口。
函数名 | 实现的方法 | 用途 |
Function<T, R> | R call<T> | 接受一个输入值并返回一个输出值,用于map()和filter()等操作中 |
Function<T1, T2, R> | R call<T1, T2> | 接受两个输入值并返回一个输出值,用于类似aggregate()和fold()等操作中 |
FlatMapFunction<T, R> | Iterable<R> call(T) | 接受一个输入值并返回任意个输出,用于flatMap()这样的操作中 |
DoubleFlatMapFunction<T> |
| 用于flatMapFunction,以生成DoubleRDD |
DoubleFunction<T> |
| 用于mapFunction,以生成DoubleRDD |
PairFlatMapFunction<T, K, V> |
| 用于flatMapToPair,以生成PairRDD<K, V> |
PairFunction<T, K, V> |
| 用于mapToPair,以生成PairRDD<K, V> |
3 基本RDD操作
对一个数据为{1,2,3,3}的RDD进行基本的RDD转化操作
函数名 | 目的 | 示例 | 结果 |
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(withReplacement, fraction, [seed]) | 对RDD采样,以及是否替换 | rdd.sample(flase, 0.5) |
|
对数据分别为{1,2,3}和{3,4,5}的RDD进行针对两个RDD的转化操作
函数名 | 目的 | 示例 | 结果 |
union() | 生成一个包含两个RDD中所有元素的RDD |
| {1,2,3, 3,4,5} |
intersection() | 求两个RDD共同的元素的RDD |
| {3} |
subtract() | 移除一个RDD中的内容 |
| {1,2} |
cartesian() | 与另一个RDD的笛卡尔积 |
| {(1,3),(1,4),…(3,5)} |
对一个数据为{1,2,3,3}的RDD进行基本的RDD行动操作
函数名 | 目的 | 示例 | 结果 |
collect() | 返回RDD中的所有元素 |
| {1,2,3,3} |
count() | 返回RDD中的元素个数 |
| 4 |
countByValue() | 各元素在RDD中出现的次数 |
| {(1,1),(2,1),(3,2)} |
take(num) | 从RDD中返回num个元素 |
| {1,2} |
top(num) | 从RDD中返回最前面的num个元素 |
| {3,3} |
takeSample(withRepla cement, fraction, [seed]) | 从RDD中返回任意一些元素 | rdd.takeSamp le(false,1) |
|
reduce(func) | 并行整合RDD中所有数据 | rdd.reduce((x, y)=>x+y) | 9 |
aggregate(zeroValue)(seq 0p,com0p) | 与reduce()相似,但是通常返回不同类型的函数 |
|
|
foreach(func) | 对RDD中的每个元素使用给定的函数 |
|
|
4 PairRDD操作
Spark为包含键值对类型的RDD提供了一些转悠的操作,这些RDD被称为PairRDD。PairRDD是很多程序的构成要素,因为他们提供了并行操作各个键或跨节点重新进行数据分组的操作接口。
pairRDD的转化操作(以键值对集合{(1,2),(3,4),(3,6)}为例)
函数名 | 目的 | 示例 | 结果 |
reduceByKey(func) | 合并具有相同键的值 | rdd.reduceByKey((x, y)=>x+y) | {(1,2),(3,10)} |
groupByKey() | 对具有相同键的值进行分组 |
| {(1,[2]),(3,[4,6])} |
combineByKey(create Combiner,mergeComb iners,partitioner) | 使用不同的返回类型合并具有相同键的值 |
|
|
mapValue(func) | 对pairRDD中的每个值应用一个函数而不改变键 | rdd.mapValues(x =>x+1) | {(1,3),(3,5),(3,7)} |
flatMapValues() | 对pairRDD中的每个值应用一个返回迭代器的函数,然后返回的每个元素都生成一个对应原键的键值对记录 | rdd.flatMapValues(x=>(x to 5)) | {(1,2),(1,3),(1,4),(1,5),(3,4),(3,5)} |
keys() | 返回一个仅包含键的RDD |
| {1,3,3} |
values() | 返回一个仅包含值的RDD |
| {2,4,6} |
sortByKey() | 返回一个根据键排序的RDD |
| {(1,2),(3,4),(3,6)} |
针对两个pairRDD的转换操作(rdd={(1,2),(3,4),(3,6)} other={(3,9)})
目的 | 示例 | 结果 | |
subtractByKey | 删掉RDD中的键与otherRDD中的键相同的元素 |
| {(1,2)} |
join | 对两个RDD进行内链接 |
| {(3,(4,9)),(3,(6,9))} |
cogroup | 将两个RDD中拥有相同键的数据分组到一起 |
| {(1,([2],[])),(3,([4,6],[9]))} |
PairRDD的行动操作(以键值对集合{(1,2),(3,4),(3,6)})
函数名 | 目的 | 示例 | 结果 |
countByKey() | 对每个键对应的元素分别计数 |
| {(1,1),(3,2)} |
collectAsMap() | 将结果以映射表的形式返回,以便查询 |
| Map{(1,2),(3,4),(3,6)} |
lookup(key) | 返回给定键对应的所有值 |
| [4,6] |