1.RDD 是spark的核心数据结构,全称是弹性分布式数据集。
本质上是一种分布式的内存抽象,表示一个只读的数据分区集合。一个RDD通常只能通过其他的RDD转换而创建,RDD定义了各种丰富的转换操作,通过转换操作,新的RDD包含了如何从其他RDD衍生所必须的信息。这些信息构成了RDD之间的依赖关系。
依赖关系具体分为两种: 窄依赖(RDD之间分区时一一对应的);宽依赖(RDD之间是多对多的关系)
而其中窄依赖的所有转换操作可以通过类似管道的方式全部执行。
宽依赖意味着数据需要在不同节点之间shuffle传输
1.1 RDD算子包括两类:
transformation:用来将RDD进行转换,构建RDD的依赖关系
action:用来触发RDD的计算,得到RDD的相关计算结果或将RDD保存到文件系统中。
概括而言:基于RDD的计算任务可描述为:从稳定的物理存储(如分布式文件系统HDFS)中加载记录,记录被传入由一组确定性操作构成的DAG(有向无环图),然后写回稳定存储。RDD还可以将数据集缓存到内存中,是的多个操作之间可以很方便的重用数据集、
容错性
基于RDD之间的依赖,一个任务流可以描述为DAG,在实际执行的时候RDD通过Lineage信息(血缘关系)来完成容错,即使出现数据分区丢失,也可以通过Lineage 信息重建分区。但是如果是长时间迭代型应用,随着时间的退役,RDD之间的Lineage信息会越来越长,如果一但过程中出错,就需要很慌的Lineage信息重建分区,性能会大大降低。
因此,RDD支持用checkpoint机制将数据保存到持久化的存储汇总,这样就可以切断之前的Lineage信息,因为checkpoint后的RDD不再需要知道它的父RDD, 可以直接从checkpoint处获取数据。
2.DataFrame和Dataset
DataFrame与RDD一样,都是不可变分布式弹性数据集。
区别是:
RDD中的数据不包含任何结构信息。
DataFrame中的数据集类似于关系型数据库中的表,按列名存储,具有Schema信息。
DataFrame的数据抽象是命名元组(对应Row类型)
Dataset比Dataframe更为强大。Dataframe本质上是一种特殊的Dataset(也就是Dataset[Row]类型)
作为DataFrame的扩展,Dataset结合了RDD和DataFrame的有点:提供类型安全和面向对象的编程接口,并引入了编码器(Encoder)的概念。
// 案例
case class Person(name:String , age:Int)
val caseClass2DS = Seq(Person("ss" , 32)).toDS()
caseClass2DS.show()
// 其中在定义Person的类就起到了Encoder的作用,在映射过程中,Encoder首先检查定义的Person类的类型是否与数据相符,如果不相符,则能够及时提供有用的错误信息、。
// 类似于DataFrame, Dataset创建之后也能够很容易地使用lambda表达式操作
其中Encoder不仅能够在编译阶段完成类型安全检查,还能够生成字节码与堆外数据进行交互,提供对各个属性的按需访问, 而不必对整个对象进行反序列化操作, 极大地减少了网络数据传输代价。