spark

Spark

  1. 什么是Spark
    Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行计算框架,Spark拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。
    Spark是Scala编写,方便快速编程。

  2. 总体技术栈讲解
    在这里插入图片描述
    回顾hadoop
    在这里插入图片描述
    spark 和 MapReduce 的区别
    都是分布式计算框架,spark 基于内存,mapreduce基于hdfs, Spark 处理数据的能力一般是mr的十倍以上,Spark中除了基于内存计算外,还有DAG有向无环图来切分任务的执行先后顺序
    MapReduce
    在这里插入图片描述
    Spark: 快除了内存计算外,还有DAG
    在这里插入图片描述

Spark的运行模式
  • local 多用于本地测试。如在 eclipse,,idea中写程序测试
  • standalone: 是Spark自带的一个资源调度框架,它支持完全分布式
  • Yarn: Hadoop 生态圈里的一个资源调度框架,Spark也是可以基于Yarn
    要基于Yarn来进行资源调度,必须实现 ApplicationMaster接口。spark实现了这个接口,所以可以基于yarn
  • Mesos 资源调度框架
Spark的执行原理

在这里插入图片描述
以上图中有四个机器节点,Driver和Worker是启动在节点上的进程,运行在JVM中的进程。
 Driver与集群节点之间有频繁的通信。
 Driver负责任务(tasks)的分发和结果的回收。任务的调度。如果task的计算结果非常大就不要回收了。会造成oom。
 Worker是Standalone资源调度框架里面资源管理的从节点。也是JVM进程。
 Master是Standalone资源调度框架里面资源管理的主节点。也是JVM进程。

MR 和 Spark的区别

1 spark 是基于内存迭代计算,MR是基于磁盘的迭代计算
2 Spark中有DAG有向无环图
3 Mr中只有map 和 reduce,相当于spark两个算子(map ,reduceByKey),spark中有多种算子

Spark 的代码流程
  1. 创建SparkConf对象
     可以设置Application name。
     可以设置运行模式及资源需求。
  2. 创建SparkContext对象
  3. 基于Spark的上下文创建一个RDD,对RDD进行处理。
  4. 应用程序中要有Action类算子来触发Transformation类算子执行。
  5. 关闭Spark上下文对象SparkContext。
package testScalaSpark

import org.apache.spark.{SparkConf, SparkContext}

object spark_wc {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setAppName("wordCount")
    conf.setMaster("local")

    val sc = new SparkContext(conf)

    sc.textFile(path="./data/words").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).foreach(println)
    sc.stop()
  }
}

SparkCore
RDD
  • 概念:RDD Resilient Distributed Dateset 弹性分布式数据集

  • RDD的五大特性

    1. RDD是由一系列的partition组成的。(和读取的文件的block数是一样的,一一对应,有几个文件就有几个分区数)
    2. 函数(算子)是作用在RDD每一个partition(split)上的。(下级RDD分区个数有上级RDD分区个数决定)
    3. RDD之间有一系列的依赖关系。
    4. 分区器是作用在K,V格式的RDD上。
    5. RDD提供一系列最佳的计算位置。利用数据处理的本地化,计算向数据移动
  • 问题:

    1. Spark读取hdfs中数据的方法textfile底层是调用的mr读取hdfs的方法,首先会用split切分block,每个split对应生成RDD的每个partition
    2. 什么是kv格式的 RDD?
      RDD中的数据是一个的tuple2数据,那么这个RDD就是KV格式的RDD
    3. 哪里体现了RDD的弹性(容错)?
      1). RDD之间有依赖关系
      2). RDD的partition 可多可少
    4. 哪里体现了RDD的分布式?
      RDD的partition是分布在多个节点上的
  • Lineage 血统 : 一系列RDD组成的依赖关系
    spark中 由一系列RDD 组成的一条链,一个有向无环图

  • 算子的分类

    • transformations 延迟算子
    • Action算子
    • 持久化算子
transformations(转换)算子 : 懒执行

延迟执行:需要action算子触发,transformation算子才执行

  • filter
    过滤符合条件的记录数,true保留,false过滤掉。
  • map
    将一个RDD中的每个数据项,通过map中的函数映射变为一个新的元素。
    特点:输入一条,输出一条数据。
  • flatMap
    先map后flat。与map类似,每个输入项可以映射为0到多个输出项。
  • sample
    随机抽样算子,根据传进去的小数按比例进行又放回或者无放回的抽样。
  • reduceByKey
    将相同的Key根据相应的逻辑进行处理。
  • sortByKey/sortBy
    作用在K,V格式的RDD上,对key进行升序或者降序排序。

在这里插入图片描述
通过上图可以看出,
transformations是由RDD类型变成RDD类型
action是由RDD变成一值类型

action 算子: 触发执行

当有一个 action算子时,就会生成一个job
我们写的scala可以看成一个 sparkapplication ,一个sparkapplication 通过看有几个Action算子就有几个job

  • count
    返回数据集中的元素数。会在结果计算完成后回收到Driver端。

  • take(n)
    返回一个包含数据集前n个元素的集合。

  • first
    first=take(1),返回数据集中的第一个元素。

  • foreach
    循环遍历数据集中的每个元素,运行相应的逻辑。

  • collect
    将计算结果回收到Driver端。

持久化算子
lines = sc.textFile(“hdfs://...”)
errors = lines.filter(_.startsWith(“ERROR”))
Mysql_errors = errors.filter(_.contain(“MySQL”)).count
http_errors = errors.filter(_.contain(“Http”)).count

上面这个代码。有两个action算子,在第一个调用count算子时回运行前两行。在第二个count调用时又会运行前两个行,会对文件重复io读取
所以需要进行RDD持久化,下面的算子都是懒执行的,最小持久化单位是partition

  • cache 默认将数据存储在内存中
def cache(): this.type = persist()

def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
  • persist 可以手动执行持久化级别

查看源码

class StorageLevel private(
    private var _useDisk: Boolean,
    private var _useMemory: Boolean,
    private var _useOffHeap: Boolean,
    private var _deserialized: Boolean,
    private var _replication: Int = 1)
object StorageLevel {
  val NONE = new StorageLevel(false, false, false, false)
  val DISK_ONLY = new StorageLevel(true, false, false, false)
  val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
  val MEMORY_ONLY = new StorageLevel(false, true, false, true)
  val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
  val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
  val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
  val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
  val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
  val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
  val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
  val OFF_HEAP = new StorageLevel(true, true, true, false, 1)

  • unpersist() 将数据从内存中卸载掉
rdd.unpersist()
  • checkpoint :

    • 将数据直接持久化到指定目录,当lineage的逻辑非常复杂,可以尝试使用checkpoint ,checkpoint 还可以切断RRD的依赖关系
    • 特殊场景使用checkpoint,对RDD使用checkpoint要慎用
    • checkpoint 可以指定到目录,可以将数据持久化到指定的目录中,当application执行完成之后,这个目录中的数据不会被清除
    • checkpoint的执行流程
      1. 当sparkjob执行完成后,Spark会从后往前回溯,找到checkpointRDD做标记
      2. 回溯完成之后,Spark框架会重新启动一个job,计算标记的RDD的数据,放入指定的checkpoint目录中
      3. 数据计算完成后,放入目录后,会切断RDD的依赖关系,当SparkApplication执行完成之后,数据目录中的数据不会被清除
      4. 优化:对哪个RDD进行checkpoint,最好先cache一下,这样在计算完成后再计算这个CheckpointRDD数据的时候可以直接在内存中拿到放在指定的目录中
  • 区别

    • 这三个持久化都是懒执行,最小持久化单位是 partiiton
    • cache 和 persist之后可以直接赋值给一个值,下次直接使用这个值,就是使用的持久化的数据
    • cache和 persist的数据,当application执行完成后就会自动清除
创建RDD
  • textFile
var rdd = sc.textFile("./data/persistData.txt")
  • parallelize
val rddtest: RDD[String] = sc.parallelize(Array[String]("a","b"))
rddtest.foreach(println)
  • makeRDD
val rddtest1: RDD[String] = sc.makeRDD(Array[String]("a","b"))
rddtest1.foreach(println)
spark基于standalone-client 提交任务

提交任务命令:
./spark-submit --master spark://node001:7077 --class …jar …
./spark-submit --master spark://node001:7077 --deploy-node client --class …jar …
在这里插入图片描述

spark 基于standalone-cluster提交任务

命令:
./spark-submit --master spark://node001:7077 --deploy-node cluster --class …jar …

在这里插入图片描述

Spark 基于Yarn-client模式提交任务

命令:
./spark-submit --master yarn --class …jar …
./spark-submit --master yarn --client --class …jar …
./spark-submit --master yarn --deploy-mode client --class …jar …
在这里插入图片描述

Spark 基于Yarn-cluster模式提交任务

命令:
./spark-submit --master yarn --class …jar …
./spark-submit --master yarn --cluster --class …jar …
./spark-submit --master yarn --deploy-mode cluster --class …jar …

在这里插入图片描述

RDD 的依赖

窄依赖:父RDD与子RDD partition之间的关系是一对一,父RDD与子RDD之间的关系是多对一
在这里插入图片描述

宽依赖(shuffle):父RDD与子RDD partition 之间的关系是一对多
在这里插入图片描述

Master(standalone):资源管理的主节点(进程)

•Cluster Manager:在集群上获取资源的外部服务(例如standalone,Mesos,Yarn )
•Worker Node(standalone):资源管理的从节点(进程) 或者说管理本机资源的进程
•Application:基于Spark的⽤用户程序,包含了driver程序和运行在集群上的executor程序
•Driver Program:用来连接工作进程(Worker)的程序
•Executor:是在一个worker进程所管理的节点上为某Application启动的⼀一个进程,该进程负责运行任务,并且负责将数据存在内存或者磁盘上。每个应⽤用都有各自独⽴立的executors
•Task:被送到某个executor上的工作单元
•Job:包含很多任务(Task)的并行计算,可以看做和action对应
•Stage:⼀个Job会被拆分很多组任务,每组任务被称为Stage(就像Mapreduce分map task和reduce task一样)
在这里插入图片描述
按照宽依赖来递归划分stage,每个stage都有一组并行的task组成
RDD,partition是不存数据的,存的是逻辑
stage的并行度由谁决定?有stage中finalRDD的partition个数决定,
一个stage中的并行的计算逻辑不一定相同的(union)
管道中数据何时落地?1)shuffle write时落地 2) 对RDD持久化时落地
如何提高stage的并行度?shuffle 算子 :reduceByKey(xxx, numpartition), join(xxx, numPartition), distince(

spark的计算模式 Pipeline

spark处理数据的模式:pipeline管道处理模式
f3(f2(f1(textFile))) 1+1+1=3

spark比mapreduce快的原因:
spark的计算结果不会上传到hdfs
如果将mapreduce中的map端也可以按照spark的模式写,其和spark基本是一致的,但是MapReduce会将map的结果放在hdfs上,但是spark是放在本地磁盘上
根本区别是:spark中可以在action算子结束后,可以从内存中读取持久化的数据。mapreduce不行
所有spark在迭代计算(RDD复用,内存持久化)时比MapReduce更高效。在非迭代时相差不是特别大
在这里插入图片描述

spark 中task的发送

DAGScheduler 中根据RDD的宽窄依赖来划分stage,然后将stage以Taskset的形式交给 TaskScheduler
TaskScheduler 遍历TaskSet发送Task到 Worker中 的 execute 中去执行,重试3次仍然失败就由DAGscheduler在重新发送Taskset给TaskScheduler (重试4次),如果失败则job失败,则application失败
在这里插入图片描述

spark资源调度和任务调度

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值