RDD介绍
RDD(Resilient Distributed Dataset,弹性分布式数据集),是Spark最为核心的概念。官方说法是RDD是只读的,分区记录的集合。
RDD具体包含了一些什么东西
rdd是一个类,它包含了数据应该在哪算,具体该怎么算,算完了放在哪个地方。它是能被序列化,也能被反序列化。
在开发的时候,rdd给人的感觉就是一个只读的数据。但是不是,rdd存储的不是数据,而是数据的位置,数据的类型,获取数据的方法,分区的方法等等。
通白的讲下RDD的五大特性
A list of partitions
RDD是一个由多个partition(某个节点里的某一片连续的数据)组成的list,将数据加载为RDD时,一般会遵守数据的本地性(一般来说一个hdfs里的block会加载为一个partition)
A function for computing each split
一个函数应用在一个RDD上,可以理解为一个函数对集合(RDD)中的每一个元素(split)进行操作。
A list of dependencies on other RDDs
一个RDD依赖于一组RDD。
Optionally, a Partitioner for key-value RDDs
可以对每一个partitioner进行再次分区。但是这个特性的先决条件是RDD必须是键值对格式的。
Optionally, a list of preferred locations to compute each split on
最佳位置。数据在哪台机器上,任务就启在哪个机器上,数据在本地,就不用走网络。但是数据最后汇总的时候还是要走网络的。
RDD可以从哪来
1.通过序列化集合的方式
2.通过读取文件的方式
3.通过其他的RDD进行transformation转换而来
RDD的缓存和容错
RDD缓存的几个应用场景
1.获取了大量数据之后,例如:从日志文件获取了数据后,因为重新获取文件成本较高
2.经过了较长的链条计算后,因为重新计算成本比较高
3.单个步骤非常消耗资源,可以在这个步骤后进行缓存
一般缓存应用准则
1.窄依赖想要设置缓存的时候,用cache
2.遇到宽依赖设置用checkpoint
persist()与checkpoint()对比
persist()只存在本机上,所以不用设置路径
checkpoint()备份到指定目录
cache()与checkpoint()对比
cache()只是缓存数据,不改变RDD的依赖关系
checkpoint()是已经生成了一个新的RDD,后面的RDD依赖关系已经改变,前面计算的结果已经汇总到一个RDD中
正常来说,当某一步失败以后,往前找的顺序为 checkpoint -> cache ->重算
RDD的依赖关系
RDD的依赖分为宽依赖和窄依赖,最主要的目的是划分Stage和设置缓存
宽依赖
依赖的RDD产生的数据不只是给我用的(父RDD的partition不只是对应一个子RDD的partition),不会有shuffle的产生
窄依赖
依赖的RDD产生的数据只给我自己,会有shuffle的产生
RDD的常见操作
RDD的常见操作分为 转换算子,执行算子等
常用的转换算子
map
对rdd中的每一个元素进行操作
mapPartition
对rdd中的每一个分区进行操作
可以在这里面创建链接器
flatMap
类似于map。1对多,可以理解成将原来的数据集拍扁了。RDD中每个元素可生成一个或多个元素构成的新RDD
例如将数组、列表拆分成单个值或字符串拆分成单个字符
flatMapValues
类似于flatMap,只不过flatMapValues是针对[K,V]中的V值进行flatMap操作。
filter
过滤,根据里面的规则返回(true的)一个过滤过后的rdd
distinct
去除RDD重复的元素,返回所有元素不重复的RDD
cache()
Cache()是persis的一种特殊情况,将RDD持久化到内存中
常用的执行算子
aggregate
根据初始化值进行对rdd种的元素进行聚合,结束之后每个分区会有一个结果,后面会根据这个分区结果再进行一次聚合
Collect
一个RDD转换成数组。
Count
返回RDD中的元素数量
First
返回RDD中的第一个元素,不排序
foreach
遍历RDD,将函数f应用于每一个元素。
需要注意如果RDD执行foreach,只会在Executor端有效,并且不是Driver端。
foreachPartition
与foreach类似,只不过是对每一个分区使用
Lookup
与foreach类似,只不过是对每一个分区使用
用于(K,V)类型的RDD,指定K值,
返回RDD中该K对应的所有V值。
persist()
persis(level:StorageLevel)可以传入缓存级别,默认是MEMORY_ONLY,此时同cache()操作
saveAsHadoopFile
将RDD存储在HDFS上的文件中
saveAsNewAPIHadoopFile
用于将RDD数据保存到HDFS上,使用新版本的Hadoop API,用法基本同saveAsHadoopFile
saveAsNewAPIHadoopDataset
可以用于将RDD保存到除了HDFS的其他存储中,比如HBase。
saveAsObjectFile
将RDD中的元素序列化成对象,存储到文件中(hdfs默认使用SequenceFile)。
saveAsSequenceFile
将RDD以SequenceFile的文件格式保存到HDFS上.
saveAsTextFile
将RDD以文本文件的格式存储到文件系统中。
saveAsHadoopDataset
可以用于将RDD保存到除了HDFS的其他存储中,比如HBase。
还有就是为什么说RDD是弹性的呢?
大概有这么几个点:
1.它可以自动进行内存和磁盘切换
2.基于lineage(血统)的高效容错,在中间某个点出错的时候,可以从它前面的某个的进行恢复
3.Task如果失败会进行特定次数的重试
4.Stage如果失败也会自动进行特定次数的重试,只计算失败的部分
5.checkpoint和persist(这个在后面会具体讲到)
6.数据调度弹性:DAG,Task和资源管理无关
7.数据分片的高度弹性