[ Spark ] RDD核心概念,工作原理

引子

​ Spark计算框架为了能够对数据进行高并发和高吞吐的处理,封装了三大数据结构,用于处理不同的应用场景。三大数据结构分别是:

1)RDD : 弹性分布式数据集

2)累加器:分布式共享只写变量

3)广播变量:分布式共享只读变量

ps:数据结构:简单理解为 数据与逻辑的组织形式和存储方式

RDD

1.RDD定义?

​ RDD(Resilient Distributed Dataset)为弹性分布式数据集,是Spark中最基本的数据处理模型。代码中是一个抽象类(子类多,使用装饰者模式扩充功能),它代表一个弹性的、不可变、可分区、里面的元素可并行计算的集合。

2.怎么理解RDD为Spark中封装的最小计算单元?

​ 仅提供数据和逻辑的结构,逻辑简单,扩展性强,当有复杂的逻辑,只需将多个RDD做关联,随task传给Executer

3.思考如何通过组合RDD实现复杂的逻辑?

​ 装饰者设计模式:以IO为例,字节流通过缓冲区包装成缓冲流,缓冲区超过阈值才会打印(批处理,提高性能),转换流也是,核心还是低级流起作用,以此方式扩展了新的功能,字节流通过字符流转为字符,再通过缓冲流,按行处理,readLine之前(new:创建包装流对象)都没有对数据的读取,它才是触发作业的执行.即惰性求值,没有行动算子的执行,context都不会启动

​ 以此方式理解RDD的数据处理方式,同上:RDD的数据只有调用collect方法时,才会真正执行业务逻辑的操作,之前的封装全是功能的扩展,与IO不同,RDD没有buff临时存数据,数据只有流转没有存储

4.如何将RDD分解为多个Task?

​ 不仅提供计算逻辑,还将数据切分,多个分区将数据分区以提高task并行度

5.RDD的综合特征?

​ 1)弹性:①存储的弹性:内存与磁盘的自动切换;②容错的弹性:数据丢失可以自动恢复;(由读取文件和分区逻辑找到重读) ③计算的弹性:计算出错重试机制;④分片的弹性:可根据需要重新分片。

​ 2)分布式:数据存储在大数据集群不同节点上

​ 3)数据集:RDD封装了计算逻辑,并不保存数据

​ 4)数据抽象:RDD是一个抽象类,需要子类具体实现

​ 5)不可变:RDD封装了计算逻辑,是不可以改变的,想要改变,只能产生新的RDD,在新的RDD里面封装计算逻辑(通过装饰者模式的丰富功能得到新的RDD)

​ 6)可分区、并行计算

6.如何确定计算任务的首选位置?

​ 1)计算数据时,可以根据计算节点的状态选择不同的节点位置进行计算

​ 2)判断计算任务task发给哪个节点最优?就近原则:优先选数据所在节点,不用拉取,减少IO

​ 3)为什么不先考虑任务发送的节点就近呢?移动数据不如移动计算

7.Yarn环境中,RDD的工作原理?

​ 1)启动Yarn集群环境

image-20220612225024235

​ 2)Spark通过申请资源创建调度节点和计算节点

img

​ 3)Spark框架根据需求将计算逻辑根据分区划分成不同的任务,多个RDD的多个逻辑形成关联,分解成多个task,放入任务池后方便调度

img

​ 4)调度节点将任务根据计算节点状态发送到对应的计算节点进行计算

img

​ 从以上流程可以看出RDD在整个流程中主要用于将逻辑进行封装,并生成Task发送给Executor节点执行计算。

​ 代码演示RDD的工作原理:

//Driver类
object Driver {
  def main(args: Array[String]): Unit = {

    val socket1 = new Socket("localhost", 9999)
    val socket2 = new Socket("localhost", 8888)

    val ds = new DS

    val out1 = socket1.getOutputStream
    val objOut1 = new ObjectOutputStream(out1)

    val task1 = new Task
    task1.logic=ds.logic
    task1.datas=ds.datas.take(2)

    objOut1.writeObject(task1)

    objOut1.close()

    socket1.close()
    println("task1发送完毕")



    val out2 = socket2.getOutputStream
    val objOut2 = new ObjectOutputStream(out2)

    val task2 = new Task
    task2.logic=ds.logic
    task2.datas=ds.datas.takeRight(2)

    objOut2.writeObject(task2)

    objOut2.close()

    socket2.close()
    println("task2发送完毕")
  }
}

//模拟数据结构,仅提供数据和逻辑
class DS extends Serializable {

  val datas = List(1, 2, 3, 4)

  /*val logic: Int => Int = (num: Int) => {
    num * 2
  }*/
  val logic:Int=>Int=_ *2
}

//task负责计算
class Task extends Serializable {

  var datas :List[Int]=_

  var logic:Int=>Int=_

  //计算
  def compute()={
    datas.map(logic)
  }
}

//计算节点1
object Executor {
  def main(args: Array[String]): Unit = {

    val server = new ServerSocket(9999)

    println("启动服务器...")

    val socket = server.accept()
    val in = socket.getInputStream
    val objIn = new ObjectInputStream(in)
    val task = objIn.readObject().asInstanceOf[Task]
    println(task.compute())


    objIn.close()
    socket.close()
    server.close()
  }
}

//计算节点2
object Executor2 {
  def main(args: Array[String]): Unit = {

    val server = new ServerSocket(8888)

    println("启动服务器...")

    val socket = server.accept()
    val in = socket.getInputStream
    val objIn = new ObjectInputStream(in)
    val task = objIn.readObject().asInstanceOf[Task]
    println(task.compute())


    objIn.close()
    socket.close()
    server.close()
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值