我们会先介绍一下RDD的概念和在spark中的定位,接下来讲解一下RDD的特点,最后给出RDD的一些基本操作函数和一个操作示例。
RDD概念
RDD:Spark的核心概念是RDD(resilientdistributed dataset),指的是一个只读的,可分区的分布式数据集,这个数据集的全部或部分可以缓存在内存中,在多次计算间重用。RDD本质就是一个数组,因此构造数据时候使用的是List(链表)和Array(数组)类型。RDD是spark的基石,它的一个角色定位如下图所示:
RDD特点
1. RDD数据只读,不可修改。如果需要修改数据,必须从父RDD转换(transformation)到子RDD。所以,在容错策略中,RDD没有数据冗余,而是通过RDD父子依赖(血缘)关系进行重算实现容错。
2. 多个RDD操作之间,数据不用落地到磁盘上,避免不必要的I/O操作。
3. RDD中存放的数据可以是java对象,所以避免的不必要的对象序列化和反序列化。
4. RDD在抽象上来说是一种元素集合,包含了数据。它是被分区的,分为多个分区,每个分区分布在集群中的不同节点上,从而让RDD中的数据可以被并行操作。(分布式数据集)
5. RDD提供了容错性,可以自动从节点失败中恢复过来。即如果某个节点上的RDD partition,因为节点故障,导致数据丢了,那么RDD会自动通过自己的数据来源重新计算该partition。这一切对使用者是透明的。
6. RDD的数据默认情况下存放在内存中的,但是在内存资源不足时,Spark会自动将RDD数据写入磁盘。(弹性)
RDD基本API
操作类型 | 函数名 | 作用 |
转化操作 | map() | 参数是函数,函数应用于RDD每一个元素,返回值是新的RDD |
flatMap() | 参数是函数,函数应用于RDD每一个元素,将元素数据进行拆分,变成迭代器,返回值是新的RDD | |
filter() | 参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD | |
distinct() | 没有参数,将RDD里的元素进行去重操作 | |
union() | 参数是RDD,生成包含两个RDD所有元素的新RDD | |
intersection() | 参数是RDD,求出两个RDD的共同元素 | |
subtract() | 参数是RDD,将原RDD里和参数RDD里相同的元素去掉 | |
cartesian() | 参数是RDD,求两个RDD的笛卡儿积 | |
行动操作 | collect() | 返回RDD所有元素 |
count() | RDD里元素个数 | |
countByValue() | 各元素在RDD中出现次数 | |
reduce() | 并行整合所有RDD数据,例如求和操作 | |
fold(0)(func) | 和reduce功能一样,不过fold带有初始值 | |
aggregate(0)(seqOp,combop) | 和reduce功能一样,但是返回的RDD数据类型和原RDD不一样 | |
foreach(func) | 对RDD每个元素都是使用特定函数 |
RDD操作实例
本实例的pom.xml所依赖的文件和上一章节《 spark环境构建及示例》里面例子的pom.xml一致,这里不再累述package org.mAegis.spark.machine.learning.engine;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.FlatMapFunction2;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.VoidFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* RDDApp
*
*/
public class RDDApp {
private final static Logger logger = LoggerFactory.getLogger(RDDApp.class);
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("rdd");
JavaSparkContext sc = new JavaSparkContext(conf);
//输入数据构造 rdd
JavaRDD<Integer> rddInput01 = sc.parallelize(Arrays.asList(1,2,3,4,5));
JavaRDD<Integer> rddInput02 = sc.parallelize(Arrays.asList(6,7,8,9,10));
JavaRDD<Integer> rddInput03 = sc.parallelize(Arrays.asList(6,7,6,7,6));
JavaRDD<Integer> rddInput04 = sc.parallelize(Arrays.asList(-1,2,3,4,5));
JavaRDD<String> rddInput05 = sc.parallelize(Arrays.asList("1:2:3","4:5"));
logger.info("rddInput01 ===>"+rddInput01.collect());
logger.info("rddInput02 ===>"+rddInput02.collect());
logger.info("rddInput03 ===>"+rddInput03.collect());
logger.info("rddInput04 ===>"+rddInput04.collect());
logger.info("rddInput05 ===>"+rddInput05.collect());
//数据缓存
rddInput01.cache();
rddInput02.cache();
rddInput03.cache();
rddInput04.cache();
rddInput05.cache();
//转化操作数据输出
JavaRDD<Integer> rddOutPutUnion = rddInput01.union(rddInput02);
logger.info("rddInput01 rddOutPutUnion rddInput02===>"+rddOutPutUnion.collect());
JavaRDD<Integer> rddOutPutDistinct = rddInput03.distinct();
logger.info("rddInput03 rddOutPutDistinct===>"+rddOutPutDistinct.collect());
JavaPairRDD<Integer, Integer> rddOutPutCartesian = rddInput01.cartesian(rddInput02);
logger.info("rddInput01 rddOutPutCartesian rddInput02===>"+rddOutPutCartesian.collect());
JavaRDD<Integer> rddOutPutSubtract = rddInput03.subtract(rddInput02);
logger.info("rddInput03 rddOutPutSubtract rddInput02===>"+rddOutPutSubtract.collect());
JavaRDD<Integer> rddOutPutIntersection = rddInput03.intersection(rddInput02);
logger.info("rddInput03 rddOutPutIntersection rddInput02===>"+rddOutPutIntersection.collect());
JavaRDD<Integer> rddOutPutFilter = rddInput04.filter(new Function<Integer, Boolean>() {
@Override
public Boolean call(Integer v1) throws Exception {
if(v1 <0) {
return false;
}
return true;
}
});
logger.info("rddInput04 rddOutPutFilter===>"+rddOutPutFilter.collect());
JavaRDD<Integer> rddOutPutSquare = rddInput01.map(new Function<Integer, Integer>() {
@Override
public Integer call(Integer v1) throws Exception {
return v1*v1;
}
});
logger.info("rddInput01 rddOutPutSquare===>"+rddOutPutSquare.collect());
// JavaRDD<String> rddOutPutFlatMap = rddInput05.flatMap(new FlatMapFunction(){
// @Override
// public Iterable call(Object t) throws Exception {
// // TODO Auto-generated method stub
// return null;
// }
//
// }
// );
// logger.info("rddInput05 rddOutPutFlatMap===>"+rddOutPutFlatMap.collect());
//行动操作数据输出
Integer rddOutPutSquareAdd = rddOutPutSquare.reduce(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
});
logger.info("rddOutPutSquare rddOutPutSquareAdd===>"+rddOutPutSquareAdd);
Integer rddOutPutFlodAdd = rddInput01.fold(0, new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
});
logger.info("rddInput01 rddOutPutFlodAdd===>"+rddOutPutFlodAdd);
Integer rddOutPutAggregate = rddInput02.aggregate(0, new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1*v2;
}
}, new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
});
logger.info("rddInput02 aggregate===>"+rddOutPutAggregate);
rddInput03.foreach(new VoidFunction<Integer>() {
@Override
public void call(Integer t) throws Exception {
t = t*2;
}
});
logger.info("rddInput03 foreach t*2===>"+rddInput03.collect());
List<Integer> rddOutPut3Collect = rddInput03.collect();
logger.info("rddInput03 rddOutPut3Collect ===>"+rddOutPut3Collect);
List<Integer> rddOutPutCollect = rddInput01.collect();
logger.info("rddInput01 rddOutPutCollect ===>"+rddOutPutCollect);
int count = (int) rddInput02.count();
logger.info("rddInput02 count ===>"+count);
Map<Integer,Long> countByValueMap = rddInput03.countByValue();
logger.info("rddInput03 countByValue ===>"+countByValueMap);
}
}
示例运行结果:
16/11/08 20:02:31 INFO RDDApp: rddInput01 ===>[1, 2, 3, 4, 5]
16/11/08 20:02:31 INFO RDDApp: rddInput02 ===>[6, 7, 8, 9, 10]
16/11/08 20:02:31 INFO RDDApp: rddInput03 ===>[6, 7, 6, 7, 6]
16/11/08 20:02:32 INFO RDDApp: rddInput04 ===>[-1, 2, 3, 4, 5]
16/11/08 20:02:32 INFO RDDApp: rddInput05 ===>[1:2:3, 4:5]
16/11/08 20:02:32 INFO RDDApp: rddInput01 rddOutPutUnion rddInput02===>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
16/11/08 20:02:33 INFO RDDApp: rddInput03 rddOutPutDistinct===>[6, 7]
16/11/08 20:02:33 INFO RDDApp: rddInput01 rddOutPutCartesian rddInput02===>[(1,6), (1,7), (1,8), (1,9), (1,10), (2,6), (2,7), (2,8), (2,9), (2,10), (3,6), (3,7), (3,8), (3,9), (3,10), (4,6), (5,6), (4,7), (5,7), (4,8), (5,8), (4,9), (4,10), (5,9), (5,10)]
16/11/08 20:02:33 INFO RDDApp: rddInput03 rddOutPutSubtract rddInput02===>[]
16/11/08 20:02:33 INFO RDDApp: rddInput03 rddOutPutIntersection rddInput02===>[6, 7]
16/11/08 20:02:34 INFO RDDApp: rddInput04 rddOutPutFilter===>[2, 3, 4, 5]
16/11/08 20:02:34 INFO RDDApp: rddInput01 rddOutPutSquare===>[1, 4, 9, 16, 25]
16/11/08 20:02:34 INFO RDDApp: rddOutPutSquare rddOutPutFlatMap===>55
16/11/08 20:02:34 INFO RDDApp: rddInput01 rddOutPutFlodAdd===>15
16/11/08 20:02:34 INFO RDDApp: rddInput02 aggregate===>0
16/11/08 20:02:34 INFO RDDApp: rddInput03 foreach t*2===>[6, 7, 6, 7, 6]
16/11/08 20:02:34 INFO RDDApp: rddInput03 rddOutPut3Collect ===>[6, 7, 6, 7, 6]
16/11/08 20:02:34 INFO RDDApp: rddInput01 rddOutPutCollect ===>[1, 2, 3, 4, 5]
16/11/08 20:02:34 INFO RDDApp: rddInput02 count ===>5
16/11/08 20:02:34 INFO RDDApp: rddInput03 countByValue ===>{6=3, 7=2}