Spark入门(二)

1、RDD概述

1.1 什么是RDD
  • RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。
    • Dataset:它是一个集合,集合里面有很多个元素
    • Distributed:rdd中的数据是进行了分布式存储,后期方便于进行分布式计算。
    • Resilient:弹性,意味着rdd的数据可以保存在内存或者是磁盘中。
1.2 RDD的五大属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-emUJjCHH-1634301972674)(基于单词统计来剖析RDD的五大属性.png)]

(1) A list of partitions
一个分区列表
	它表示一个rdd中有很多个分区,后期spark任务的计算是以分区为单位进行计算。一个分区就对应上一个task线程。
	val rdd=sc.textFile(文件)
	val rdd=sc.textFile(文件,parNums)
	该文件的block个数小于等于2,这个时候rdd的分区数就是2
	该文件的block个数大于2,  这个时候rdd的分区数就跟block个数相等
	
	

(2) A function for computing each split
  作用在每一个分区中的函数
  var rdd2=rdd1.map(x=>(x,1))


(3) A list of dependencies on other RDDs
  一个RDD会依赖于其他多个RDD,这里就涉及到RDD与RDD之间的依赖关系,后期spark任务的容错机制就是根据这个特性而来。
   var rdd2=rdd1.map(x=>(x,1))

(4) Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
    (可选性) 一个分区函数,针对于一个kv类型的RDD才会有分区函数(必须要产生shuffle)。对于不是kv类型的RDD,它的分区函数是None. 
    spark提供了2种shuffle机制,
    第一种默认值:hashPartitioner ------->  key.hashcode % 分区数=分区号
    第二种RangePartitioner: 基于一个范围的分区策略。


(5) Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
    (可选性)   一个优先的数据分区列表,这里就涉及到数据本地性和数据位置最优。
    spark后期再进行任务分配的时候,会优先考虑存有数据的worker节点来进行任务的计算。
1.3 创建RDD
  • 1、通过一个已经存在的scala集合去构建
    • val rdd1=sc.parallelize(List(1,2,3,4),2)
  • 2、通过加载外部的数据源去构建
    • val rdd2=sc.textFile("/words.txt")
  • 3、通过一个已经存在的rdd去构建
    • val rdd3=rdd2.flatMap(x=>x.split(" "))

2、RDD中算子操作

  • rdd中算子一共可以分为2类

  • transformation(转换)

    • 它是一个转换,可以实现把一个rdd转换生成一个新的rdd,它不会立即触发任务的运行,它是延迟加载。
      • 它只是记录下作用在rdd的上转换操作
      • 比如
        • flatMap/map/reduceByKey/sortBy
  • action (动作)

    • 它会触发任务的真正运行

      • 比如

        • collect/saveAsTextFile

3、RDD的依赖关系

在这里插入图片描述

  • rdd与rdd之间有依赖关系

    • 窄依赖
      • 窄依赖指的是每一个父RDD的Partition最多被子RDD的一个Partition使用
        总结:窄依赖我们形象的比喻为独生子女
      • 窄依赖不会产生shuffle
    • 宽依赖
      • 宽依赖指的是多个子RDD的Partition会依赖同一个父RDD的Partition
        总结:宽依赖我们形象的比喻为超生
      • 宽依赖会产生shuffle

4、lineage(血统)

  • rdd后期会进行大量的转换操作,我们把rdd的这些操作行为记录下来,记录下来的信息我们就称为lineage(血统)
  • 血统好处
    • 当前某一个rdd的分区数据丢失了,可以通过血统这一层关系来重新计算恢复得到。
    • 这里spark的任务容错机制就是根据血统而来。

5、RDD的缓存机制

5.1 RDD的缓存是什么
  • 可以把一个rdd的结果数据进行缓存,后续有其他的job需要依赖于前面rdd的结果数据,这个时候可以直接从缓存中获取得到,避免重复计算。
5.2 如何设置缓存
  • rdd中提供了设置缓存的2种方式
    • cache:默认是将数据缓存在内存中,其本质是调用persist方法
    • persist:可以把数据缓存内存或者是磁盘中,它里面可以设置丰富的缓存级别,这些缓存级别都封装在一个object 中,这个object的名称Storagelevel
  • 以上这个2个方法并不是调用之后就立即执行,后续是需要一个action操作,才会触发缓存真正执行。
5.3 如何清除缓存
  • 手动清除
    • 调用rdd的unpersist 清除缓存数据:rdd1.unpersist(true)
  • 自动清除:对于程序来说,如果我们设置了缓存,后期程序结束了,它会自动清除
5.4 什么时候设置缓存
  • 1、一个rdd后期被使用了多次
    • val rdd2=rdd1.flatMap(_.split(" "))
    • val rdd3=rdd1.map(x=>(x,1))
    • 上面的rdd1被使用了多次,每一次使用都需要先把rdd1的结果数据先计算一下,这个时候就可以对rdd1设置缓存,避免后续的rdd需要前面的结果。
  • 2、某一个rdd的数据来之不易 是经过多个转换而来
    • val rdd2=rdd1.flatMap(_.split(" ")).map().xxxxx.xxxxxxx.xxxxxxx.xxxxxxx.xxx.xxx

6、DAG有向无环图和划分stage

6.1 什么是DAG
  • DAG就是按照rdd的一系列操作最后生成了一个有方向无闭环的图,这个图我们就称为DAG有向无环图。

    按照操作逻辑划分成不同的stage(不同的调度阶段)

在这里插入图片描述

在这里插入图片描述

7、spark任务调度

在这里插入图片描述

(1)Driver会运行客户端main方法中的代码,代码就会构建SparkContext对象,在构建SparkContext对象中,会创建DAGScheduler和TaskScheduler,然后按照rdd一系列的操作生成DAG有向无环图。最后把DAG有向无环图提交给DAGScheduler。

(2)DAGScheduler拿到DAG有向无环图后,按照宽依赖进行stage的划分,这个时候会产生很多个stage,每一个stage中都有很多可以并行运行的task,把每一个stage中这些task封装在一个taskSet集合中,最后提交给TaskScheduler。

(3)TaskScheduler拿到taskSet集合后,依次遍历每一个task,最后提交给worker节点的exectuor进程中。task就以线程的方式运行在worker节点的executor进程中。

8、spark的容错机制之checkpoint

什么是checkpoint
  • cache
    • 默认是把数据缓存在内存中,后续操作起来速度比较快
    • 但是由于进程或者是服务器挂掉了,这个时候内存中的数据肯定是丢失,也就是说cache不是非常安全,数据丢失的概率比较大。
  • persist
    • 有丰富的缓存级别,可以把数据缓存在磁盘中,然后需要用到该数据,可以进行磁盘io操作获取得到,这一点比cache速度会慢点,但是比cache安全点
    • 这里同样也有数据丢失的可能性(磁盘损坏、系统管理员由于误操作把本地数据清除掉了)
  • checkpoint
    • 它是提供了一个相对而言更加可靠的持久化数据的方式
    • 它可以把rdd的数据写入到分布式文件系统(HDFS)去保存,利用了hdfs高可靠,多个副本机制最大程度保证数据不丢失。
区别
  • cache和persist:
    • 这2个方法都可以将rdd的数据进行缓存,后续都要有一个action操作,才会触发缓存任务的执行
    • 它不会改变rdd的血统。整个程序结束之后,这些缓存数据自己被清除了。
  • checkpoint:
    • 可以把数据持久化到hdfs上,这个时候先rdd.checkpoint操作,然后也需要一个action。
    • 一个action操作就是一个job,在这里首先它会执行action这个job,执行完成之后,它会开启一个新的job来执行checkpoint操作,写入之前设置的文件系统持久化, 也就是说在这里比cache和persist多了一个job。它会改变rdd的血统。checkpoint 执行完后,rdd 已经没有依赖 RDD,只有一个checkpointRDD,checkpoint 之后,RDD的lineage就改变了
如何使用checkpoint
  • 1、通过sparkContext对象设置checkpoint目录,用于保存rdd的数据
    • sc.setCheckpointDir("/ckDir")
  • 2、对需要持久化的rdd调用一个方法checkpoint方法
    • val rdd1=sc.textFile("/words.txt")
    • rdd1.checkpoint
  • 3、后续需要有个action操作,触发checkpoint的执行
    • rdd1.collect
数据丢失之后的恢复顺序
  • 首先看一写有没有设置cache,如果有,直接从cache获取得到
  • 如果没有cache,看一下有没有做checkpoint,如果有就直接从checkpoint获取得到
  • 如果没有checkpoint,利用血统这层关系来重新计算恢复得到。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值