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 的所在位置应该是优先计算的地位