今天讲的是RDD。RDD是个相当抽象的概念,它是一个逻辑概念,并不是很好理解,但它确实整个spark里的一个非常核心的东西,甚至不夸张的讲,就通过RDD这个概念就能把spark整个底层机制给串起来。
RDD, 英文名:residenta distributed dataset, 弹性分布式数据集。下面,就是展示我语文功底的时候了。就分析这个词,就让你知道RDD的特性。
弹性 分布式 数据集
1.弹性 究竟多Q弹呢?正常情况下,数据是存放到内存里的,但是如果说内存放不下这么多数据时,这时候就会写到磁盘。RDD的这种自动进行内存和磁盘之间权衡和切换的机制,就是RDD的弹性的特点所在。对用户来说是透明的。
2.分布式
简单说就是数据存放到不同机器上,1个Rdd=多个Partition,Parition就是分区,这个分区其实是个非常重要的概念,为什么这么说呢?Paritition本质上只是一部分数据,它和Task是一一对应的,task在提交的时候又有什么依据呢?其实又跟这个有关系
task在分配的时候又是依据什么算法分配的?这里面又涉及到数据本地优先原则,所以我一直强调说分布式在这里不可忽视。
3.数据集
数据集这个概念也是相当有意思,你以为就是简单的一堆数据吗?答案是否定 ,RDD可以理解为“数据+对数据操作”,RDD的基本单位是partition,以及每个分片的操作函数,也就是算子。当然了,RDD还“记录”着自身的血缘关系,对parent RDD的依赖,官方叫“lineage”。仅仅这么简单吗?这涉及到RDD的容错性,当某个节点挂掉了,这时候数据就丢失了,怎么办?spark程序挂掉了?那这也太low了,RDD是有很强的容错性的,当它发现自己的数据丢失了以后,会自动从自己来源的数据进行重计算,重新获取自己这份数据,这就是“血缘关系”。
上面说了算子这个概念,在讲算子之前,我们先来讲RDD的依赖关系:
RDD之间的依赖关系可以分为两类,即:
窄依赖(narrow dependencies):子RDD的每个分区依赖于常数个父分区(即与数据规模无关),也可以理解为没有触发shuffle。
宽依赖(wide dependencies):子RDD的每个分区依赖于所有父RDD分区。也可以理解为触发了shuffle。例如,map产生窄依赖,而join则是宽依赖(除非父RDD被哈希分区)。
重点是shuffle操作,这个是个非常重要的点,数据倾斜也就是反生在这个过程。DAGScheduler就是根据是否发生宽依赖来切分stage。
算子分成两类:transformation, action
transformation和action又有什么区别呢?transformation是懒加载,它只是记录了RDD转化关系,并不会真正开始计算,而action,是真正触发程序开始执行。
RDD缓存(cache, persist)
RDD缓存主要是为了提高效率,当你要重用某个计算好的RDD,就可以直接取缓存好的RDD,而不是从头再来计算一次,这样浪费时间。Spark提供了多种缓冲级别,以便于用户根据需要进行选择,可以基于内存,或磁盘,或双重缓存保险:
这节主要讲了RDD的概念,如果要想深刻理解,还是要动手进行操作。下节主要讲解RDD操作实践。
欢迎关注个人微信公众号:BigData共享
文章来自: