栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[ 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集群环境

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

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

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

​ 从以上流程可以看出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=_ *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()
  }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/975422.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号