RDD
什么是RDD
- RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。
- RDD具有数据流模型的特点:自动容错、位置感知性调度和可伸缩性。
- RDD允许用户在执行多个查询时显式地将数据缓存在内存中,后续的查询能够重用这些数据,这极大地提升了查询速度。
IO流和RDD读取数据的区别:IO流只能读取具体的数据格式的数据;RDD可以读取多格式多来源的数据,且RDD不可变,只可返回新的RDD。
常提起的RDD的概念:
- 一组分区,即数据集的基本组成单位
- 一个计算每个分区的函数
- RDD之间的依赖关系
- 一个Partitioner,即RDD的分片函数
- 一个列表,存储存取每个Partition的优先位置(preferred location)
RDD表示只读分区的数据集,对RDD进行改动,只能通过RDD的转换操作,由一个RDD得到一个新的RDD,新的RDD包含了从其他RDD衍生所必须的信息,RDD们之间存在依赖,RDD的执行是按照血缘关系延时计算的。
如果血缘关系较长,可以通过持久化RDD(例如checkpoint)来切断血缘关系。
spark中所有的RDD方法都成为算子,主要分为两类:
转换算子
行动算子
RDD的创建主要分为3种:
-
在集合中创建RDD
parallelize => val rdd[int] = parallelize(Array(1,2,3,4),numpartition) makeRDD => val rdd[int] = sc.makeRDD(List(1,2,3,4))
-
从外部存储创建RDD
val rdd[sring] = sc.textFile("hdfs://centos7:9000/ ...txt")
-
从其他RDD转换
应用场景
- 使用程序中的集合创建RDD,主要用于进行测试,可以在实际部署到集群运行之前,自己使用集合构造测试数据,来测试后面的spark应用的流程。
- 使用本地文件创建RDD,主要用于的场景为:在本地临时性地处理一些存储了大量数据的文件。
- 使用HDFS文件创建RDD,应该是最常用的生产环境处理方式,主要可以针对HDFS上存储的大数据,进行离线批处理操作。
RDD的转换可大致分为两种类型:
一、value类型:
(map(func),返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成)
(mappartition()可以对一个RDD中所有的分区进行遍历;效率优于map算子,减少了发送到执行器执行的交互次数;可能会出现OOM)网络交互越多,效率越低 (mappartitionwithIndex,可返回分区信息)
(flatmap(func) 类似于map,但是每一个输入元素可以被映射为0或多个输出元素,所以func应该返回一个序列,而不是单一元素。)flatmap(x=>List())
(union(otherDataset),对源RDD和参数RDD求并集后返回一个新的RDD)
(subtract(otherDataset),计算差的一种函数,去除两个RDD中相同的元素,不同的RDD将保留下来)
(intersection(otherDataset),对源RDD和参数RDD求交集后返回一个新的RDD)
二、k-v类型
(partitionBy(k,v)RDD,对pairRDD进行分区操作,如果原有的partionRDD和现有的partionRDD是一致的话就不进行分区,否则就会生成ShuffleRDD,即会产生shuffle过程)
val rdd = sc.parallelize(Array((1,"aa"),(2,"bb"),(3,"cc"),(4,"dd"))) =>rdd.partitions.size = 4
val rdd2 = rdd.partitionBy(分区器) =>rdd2.partitions.size = 2
(GroupBy(),利用groupByKey也是对每个key进行操作,但只是生成一个sequence)
val words = Array("one","one","one","two","two","three","three","four")
val wordPairRDD = ac.parallelize(words).map(word=>(word,1))
val group = wordPairRDD.groupByKey() =>group.collect()
group.map(t=>(t._1,t._2.sum))
(reduceByKey(numTasks)在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同的key的值聚到一起,reduce任务的个数可以通过第二个可选的参数来设置)
RDD的算子可大致分为3类:
-
Transformation(转换):根据数据集创建一个新的数据集,计算后返回一个新RDD;例如:一个rdd进行map操作后生了一个新的rdd。
-
Action(动作):对rdd结果计算后返回一个数值value给驱动程序;
例如:collect算子将数据集的所有元素收集完成返回给驱动程序。 -
控制算子
转换
map(func) 返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成
filter(func) 返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成
flatMap(func) 类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)
mapPartitions(func) 类似于map,但独立地在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T] => Iterator[U]
mapPartitionsWithIndex(func) 类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int, Interator[T]) => Iterator[U]
union(otherDataset) 对源RDD和参数RDD求并集后返回一个新的RDD
intersection(otherDataset) 对源RDD和参数RDD求交集后返回一个新的RDD
groupByKey([numTasks]) 在一个(K,V)的RDD上调用,返回一个(K, Iterator[V])的RDD
reduceByKey(func, [numTasks]) 在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,与groupByKey类似,reduce任务的个数可以通过第二个可选的参数来设置
sortByKey([ascending], [numTasks]) 在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
sortBy(func,[ascending], [numTasks]) 与sortByKey类似,但是更灵活
join(otherDataset, [numTasks]) 在类型为(K,V)和(K,W)的RDD上调用,返回一个相同key对应的所有元素对在一起的(K,(V,W))的RDD
cogroup(otherDataset, [numTasks]) 在类型为(K,V)和(K,W)的RDD上调用,返回一个(K,(Iterable,Iterable))类型的RDD
coalesce(numPartitions) 减少 RDD 的分区数到指定值。
repartition(numPartitions) 重新给 RDD 分区
repartitionAndSortWithinPartitions(partitioner) 重新给 RDD 分区,并且每个分区内以记录的 key 排序
动作
reduce(func) reduce将RDD中元素前两个传给输入函数,产生一个新的return值,新产生的return值与RDD中下一个元素(第三个元素)组成两个元素,再被传给输入函数,直到最后只有一个值为止。
collect() 在驱动程序中,以数组的形式返回数据集的所有元素
count() 返回RDD的元素个数
first() 返回RDD的第一个元素(类似于take(1))
take(n) 返回一个由数据集的前n个元素组成的数组
takeOrdered(n, [ordering]) 返回自然顺序或者自定义顺序的前 n 个元素
saveAsTextFile(path) 将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark将会调用toString方法,将它装换为文件中的文本
saveAsSequenceFile(path) 将数据集中的元素以Hadoop sequencefile的格式保存到指定的目录下,可以使HDFS或者其他Hadoop支持的文件系统。
saveAsObjectFile(path) 将数据集的元素,以 Java 序列化的方式保存到指定的目录下
countByKey() 针对(K,V)类型的RDD,返回一个(K,Int)的map,表示每一个key对应的元素个数。
foreach(func) 在数据集的每一个元素上,运行函数func
foreachPartition(func) 在数据集的每一个分区上,运行函数func
控制算子
cache 对于重复使用的算子,进行cache做缓存使用,数据只保存在内存中,性能提升
persist 可选取持久化级别
checkPoint 数据容错,当数据计算的时候,机器挂了,重新追溯到checkPoint的目录下checkPoint是将RDD持久化到磁盘中,还可以切断RDD之间的依赖关系。