RDD(Resilient Distributed Datasets)弹性的分布式数据集,又称Spark core,它代表一个只读的、不可变、可分区,外面的元素可分布式并行计算的数据集。
RDD是一个很形象的概念,不易于了解,然而要想学好Spark,必须要把握RDD,相熟它的编程模型,这是学习Spark其余组件的根底大数据培训。
• Resilient(弹性的)

提到大数据必提分布式,而在大规模的分布式集群中,任何一台服务器随时都有可能呈现故障,如果一个task工作所在的服务器呈现故障,必然导致这个task执行失败。此时,RDD的"弹性的"特点能够使这个task在集群内进行迁徙,从而保障整体工作对故障服务器的平稳过渡。对于整个工作而言,只需重跑某些失败的task即可,而无需齐全重跑,大大提高性能
• Distributed(分布式)

首先理解一下分区,即数据依据肯定的切分规定切分成一个个的子集。spark中分区划分规定默认是依据key进行哈希取模,切分后的数据子集能够独立运行在各个task中并且在各个集群服务器中并行执行。当然使用者也能够自定义分区规定,这个还是很有利用场景的,比方自定义分区打散某个key特地多的数据集以防止数据歪斜(数据歪斜是大数据畛域常见问题也是调优重点,后续会独自解说)
• Datasets(数据集)

初学者很容易误会,认为RDD是存储数据的,毕竟从名字看来它是一个"弹性的分布式数据集"。然而,笔者强调,RDD并不存储数据,它只记录数据存储的地位。外部解决逻辑是通过使用者调用不同的Spark算子,一个RDD会转换为另一个RDD(这也体现了RDD只读不可变的特点,即一个RDD只能由另一个RDD转换而来),以transformation算子为例,RDD彼此之间会造成pipeline管道,无需等到上一个RDD所有数据处理逻辑执行完就能够立刻交给下一个RDD进行解决,性能也失去了很大晋升。然而RDD在进行transform时,不是每解决一条数据就交给下一个RDD,而是应用小批量的形式进行传递(这也是一个优化点)
• lineage

既然Spark将RDD之间以pipeline的管道连接起来,如何防止在服务器呈现故障后,重算这些数据呢?这些失败的RDD由哪来呢?这就牵涉到,Spark中的一个很重要的概念:Lineage即血统关系。它会记录RDD的元数据信息和依赖关系,当该RDD的局部分区数据失落时,能够依据这些信息来从新运算和复原失落的分区数据。简略而言就是它会记录哪些RDD是怎么产生的、怎么“失落”的等,而后Spark会依据lineage记录的信息,复原失落的数据子集,这也是保障Spark RDD弹性的关键点之一
• Spark缓存和checkpoint

• 缓存(cache/persist)
cache和persist其实是RDD的两个API,并且cache底层调用的就是persist,区别之一就在于cache不能显示指定缓存形式,只能缓存在内存中,然而persist能够通过指定缓存形式,比方显示指定缓存在内存中、内存和磁盘并且序列化等。通过RDD的缓存,后续能够对此RDD或者是基于此RDD衍生出的其余的RDD解决中重用这些缓存的数据集
容错(checkpoint)
实质上是将RDD写入磁盘做检查点(通常是checkpoint到HDFS上,同时利用了hdfs的高可用、高牢靠等特色)。下面提到了Spark lineage,但在理论的生产环境中,一个业务需要可能十分非常复杂,那么就可能会调用很多算子,产生了很多RDD,那么RDD之间的linage链条就会很长,一旦某个环节呈现问题,容错的老本会十分高。此时,checkpoint的作用就体现进去了。使用者能够将重要的RDD checkpoint下来,出错后,只需从最近的checkpoint开始从新运算即可应用形式也很简略,指定checkpoint的地址[SparkContext.setCheckpointDir("checkpoint的地址")],而后调用RDD的checkpoint的办法即可。
• checkpoint与cache/persist比照

• 都是lazy操作,只有action算子触发后才会真正进行缓存或checkpoint操作(懒加载操作是Spark工作很重要的一个个性,不仅实用于Spark RDD还实用于Spark sql等组件)
• cache只是缓存数据,但不扭转lineage。通常存于内存,失落数据可能性更大
• 扭转原有lineage,生成新的CheckpointRDD。通常存于hdfs,高可用且更牢靠

• RDD的依赖关系
Spark中应用DAG(有向无环图)来形容RDD之间的依赖关系,依据依赖关系的不同,划分为宽依赖和窄依赖

通过上图,能够很容易得出所谓宽依赖:多个子RDD的partition会依赖同一个parentRDD的partition;窄依赖:每个parentRDD的partition最多被子RDD的一个partition应用。这两个概念很重要,像宽依赖是划分stage的要害,并且个别都会伴有shuffle,而窄依赖之间其实就造成前文所述的pipeline管道进行解决数据。(图中的map、filter等是Spark提供的算子,具体含意大家能够自行到Spark官网理解,顺便感受一下scala函数式编程语言的弱小)。
RDD的属性:
1.分区列表(数据块列表,只保留数据地位,不保留具体地址)
2.计算每个分片的函数(依据父RDD计算出子RDD)
3.RDD的依赖列表
4.RDD默认是存储于内存,但当内存不足时,会spill到disk(可通过设置StorageLevel来管制)
5.默认hash分区,可自定义分区器
6.每一个分片的优先计算地位(preferred locations)列表,比方HDFS的block的所在位置应该是优先计算的地位