Spark学习

Yarn

  • yarn与zoomkeeper有什么样的关系?

Yarn的核心功能在于资源调度与管理,而ZooKeeper的核心功能在于分布式系统中的一致性服务。

Yarn:

Yarn是一个分布式资源调度器组件。这个组件的主要作用是在每次接收到请求后,会查看当下的各个子节点的状况,统筹出运算资源的调度方案来保证任务可以顺利执行。通常来说,Yarn所调度的资源常常包括磁盘空间的资源,内存的资源和通讯带宽的资源等。Yarn是Hadoop V2.0开始引入的一个组件,这个组件可以说是针对Hadoop1.0系统所爆露出的计算资源使用不合理等设计上的问题进行的修正和补充。

Zookeeper:

ZooKeeper是一个分布式的一致性服务组件。分布式系统最大的困难之处在于如何保证系统内各个节点服务器所操作或处理的数据是一致的,或者各自的配置信息是相同的,而ZooKeeper的价值就在于实现了基于分布式的统一化配置管理,命名服务,状态同步等

通俗理解:

Zookeeper和Yarn是一起工作的,它们一起管理资源。
举例说明:在一个分布式系统上。现在有个事要办。我们要找这个系统办这个事,就要通知yarn。打个比方,yarn的master node看看这个系统里有很多node,看看谁有空,谁有能力(cpu、内存、等)来干这个事。然后把任务分配给合适的node来办这个事。
这个时候系统面临一个危险。那就是在分布式系统中,failure成为常态。
yarn master node管理着很多个node,管理着它们哪一个出问题了。危险在于master自己坏了怎么办。
常见的分布式系统出问题的解决办法是我们总保持有一个待命的,到需要的时候顶上。yarn里的Resource Manager也有待命的。当一个Resource Manager坏了,或者需要升级更新,另一个Resource Manager要接手。这时候麻烦来了,新的Resource Manager怎么知道哪个任务已经完成,哪个还没有,用户想执行的任务到什么状态了,一个任务所必须的先决条件任务是否已经完成。
这个情形中,Yarn自己成了Single point of failure。 新启动的Resource Manager成了这个分布式系统的另外一个大脑。两个大脑管理同一套资源,就可能有不一致的地方。
要解决这个问题,我们就要保存Yarn自身的各种状态,比如都收到了哪些任务,各个任务都执行到了什么状态,收到了哪些安全许可。这些东西保存在Resource Manager State Store里。 Resource Manager State . Store自己怎么管理呢。好几种办法,存在内存,存在文件,或者另外一个更容易的办法就是Zookeeper了。
Zookeeper控制着什么时候,谁可以读写这个Resource Manager State Store.
Zookeeper自己也是个cluster,它也是Fault Tolerance(容错)的,我们就省去了自己管理这个资源的各种麻烦。
Zookeeper保存着它所管理的系统的各种状态,可以保证任何时候都只有一个版本的系统状态。即便是Yarn的Master坏了,重启了,正在升级,也不会出现冲突。所以说起来,Yarn和Zookeeper的功能是不一样的,对于一套完整的系统,两者都需要使用。

Yarn的三大组件

  • ResourceManager :资源管理器
  • ApplicationMaster:负责任务的调度和监控
  • NodeManager:执行Task

在这里插入图片描述
在这里插入图片描述

  • Client : 向ResourceManager提交Job Submission
  • NodeManager:向ResourceManager提交节点状态
  • Application Master:向ResourceManager发送申请资源的请求

ResourceManager

调度器Schedule

  1. 负责资源管理与资源分配
  2. 接收来自Application Master的申请资源请求
  3. 集群中的资源以容器的形式分配给提出申请的应用程序

容器:

封装了一定数量的CPU、内存、磁盘等资源,从而限定每个应用程序可以使用的资源量

应用程序管理器Application Manager

  • ( 1 ) 当 用 户 作 业 提 交 时 , ApplicationMaster ResourceManager 协商获取资源,ResourceManager 会以容器的形式为 ApplicationMaster分配资源;
  • (2)把获得的资源进一步分配给内部的 各个任务(Map任务或Reduce任务),实现资源的“二次分配”;
  • (3)与NodeManager保持交互通信,进行应用程序的启动、运行、监控和停止,监控申请到的资源的使用情况,对所有任务的执行进度和状态进 行监控,并在任务发生失败时执行失败恢复(即重新申请资源重启任 务);
  • (4)定时向ResourceManager发送“心跳”消息,报告资源的使用 情况和应用的进度信息;
  • (5)当作业完成时,ApplicationMaster 向 ResourceManager注销容器,执行周期完成

在这里插入图片描述

Yarn工作流程

前三步: 提交代码、申请资源、App注册

  • ApplicationMaster 被创建后会首先向 ResourceManager 注册
  • ApplicationMaster 采 用 轮 询 的 方 式 通 过 RPC 协 议向ResourceManager申请资源
  • ResourceManager 以 “ 容 器 ” 的 形 式 向 提 出 申 请 的 ApplicationMaster 分配资源
  • 当ApplicationMaster要求容器启动任务时,它会为任务设置好运 行环境(包括环境变量、JAR 包、二进制程序等),然后将任务启动命令写到一个脚本中,最后通过在容器中运行该脚本来启动任务)
  • 各个任务通过某个 RPC 协议向 ApplicationMaster 汇报自己的状 态和进度
  • 应用程序运行完成后,ApplicationMaster向ResourceManager的应
    用程序管理器注销并关闭自己

Spark基本概念

  • RDD: Resilient Distrubuted Dataset
    是分布式内存的抽象概念,提供了一种高度受限的共享内存模型

  • DAG : Directed Acyclic Graph 有向无环图
    反映RDD之间的依赖关系

  • Executor:运行在工作节点Worker Node的一个进程,负责运行任务,并为应用程序存储数据

  • 应用:Spark程序

  • 任务:Execute上的工作单元

  • 作业:一个作业包含多个RDD及作用于RDD上的各个操作

  • 阶段Stage:作用的基本调度单位,一个作业会分为多组任务,每组任务被称为阶段

三大数据结构

  1. RDD
  2. 累加器 :分布式共享只写变量
  3. 广播变量: 分布式共享只读变量

Spark的三大优势:

  1. Spark是基于MapReduce之上的,但不限于Map和Reduce的操作,还提供多种数据集的操作
  2. 内存计算,中间结果直接放在内存中,减少IO开销
  3. DAG的任务调度执行机制
  • 最大的优点:从内存中读取结果和从磁盘中读取结果的区别:快!

Spark的组件:

  1. Spark Core : 核心是数据批处理,内存计算、任务调度、部署模 式、故障恢复、存储管理
  2. Spark SQL:统一处理关系表和RDD
  3. Spark Streaming:支持高吞吐量、可容错处理的实时流数据处理,其 核心思路是将流数据分解成一系列短小的批处理作业,每个短小的批 处理作业都可以使用Spark Core进行快速处理
  4. MLlib
  5. GraphX :海量数据的图计算

Spark的架构

Cluster Manager

集群资源管理器

Worker Node

运行任务的工作节点

Driver

每个应用的任务控制节点

Executor

每个工作节点上负责具体任务的执行过程

  • 一个Application有一个专属的Executor
  • 多线程并行执行任务

优点:

  1. 采用多线程来执行任务,减少任务的启动开销
  2. Executor中有一个有一个 BlockManager存储模块,会将内存和磁盘共同作为存储设备,当需要多 轮迭代计算时,可以将中间结果存储到这个存储模块里,下次需要时 就可以直接读该存储模块里的数据,而不需要读写到HDFS等文件系统里,因而有效减少了IO开销;或者在交互式查询场景下,预先将表缓存到该存储系统上,从而可以提高读写IO性能

在这里插入图片描述
在 Spark 中

  • 一个应用(Application)由一个任务控制节点(Driver)和 若干个作业(Job)构成
  • 一个作业Job由多个阶段(Stage)构成
  • 一个阶段Stage由多个任务(Task)组成

当执行一个应用时,任务控制节点Driver会向集群管理器(Cluster Manager)申请资源,启动Executor,并向Executor发送应用程序代码和文件,然后在 Executor 上执行任务,运行结束后执行结果会返回给任务控制节点,或者写到HDFS或者其他数据库中

在这里插入图片描述

工作流程

(1)当一个Spark应用被提交时,首先需要为这个应用构建起基本 的运行环境,即由任务控制节点(Driver)创建一个SparkContext,由 SparkContext负责和资源管理器(Cluster Manager)的通信以及进行资源的申请、任务的分配和监控等。SparkContext 会向资源管理器注册并申请运行Executor的资源。
(2)资源管理器为Executor分配资源,并启动Executor进程, Executor运行情况将随着“心跳”发送到资源管理器上。
(3)SparkContext 根据 RDD 的依赖关系构建 DAG 图,DAG 图提 交给 DAG 调度器(DAGScheduler)进行解析,将DAG图分解成多个 “阶段”(每个阶段都是一个任务集),并且计算出各个阶段之间的依 赖 关 系 , 然 后 把 一 个 个 “ 任 务 集 ” 提 交 给 底 层 的 任 务 调 度 器(TaskScheduler)进行处理;Executor 向 SparkContext 申请任务,任务调度器将任务分发给 Executor 运行,同时SparkContext将应用程序代码
发放给Executor。
(4)任务在Executor上运行,把执行结果反馈给任务调度器,然后反馈给DAG调度器,运行完毕后写入数据并释放所有资源。

在这里插入图片描述

RDD

概念:RDD是一个分布式对象集合,是一个只读的记录分区的集合。

  • 不能修改,只能在稳定的物理储存中数据集来创建RDD
  • 最小执行任务单元,RDD会分解成一个一个的Task分发给Executor
  • 复杂的逻辑通过RDD进行串联,完成需求

何谓弹性?

存储的弹性:内存与磁盘的自动切换;
容错的弹性:数据丢失可以自动恢复;
计算的弹性:计算出错重试机制;
分片的弹性:可根据需要重新分片。

Transformation 转换

接收RDD,返回RDD
在这里插入图片描述

Action 操作

接收RDD,返回非RDD,一个值或者一个结果

RDD适合对数据集中元素执行相同操作的批式处理,粗粒度

RDD执行过程:

  1. 读入外部数据源
  2. 一系列转换操作
  3. 最后一个转换经过Action处理,输出外部数据源
  • 惰性调用:转换操作只是改变RDD的相互转换关系(Lineage 血缘关系),不触发真正的计算,只有Action操作会触发计算

Spark会根据RDD的依赖关系生成DAG,从头开始计算

在这里插入图片描述

RDD特性

  1. 高容错:

    • RDD只读不修改,如果修改就产生父子血缘关系,如果数据发生错误,只需修改lineage,无需回滚系统
  2. 中间结果持久化到内存

  3. 存放的数据可以是java对象,避免对象的序列化和反序列化开销

RDD依赖关系

  • 宽依赖
    一个父分区对应多个子分区

    • 下游 RDD 的每个分区与上游
      RDD(也称之为父 RDD)的每个分区都有关,是多对多的关系
      groupBykey,sortByKey
  • 窄依赖
    一个父分区对应一个子分区,或者多个父分区对应一个子分区
    map,filter,union

RDD缓存

如果在应用程序中多次使用同一个 RDD,可以将该 RDD 缓存起来,该 RDD 只有在第一次计算的时候会根据血缘关系得到分区的数据,在后续其他地方用到该 RDD 的时候,会直接从缓存处取而不用再根据血缘关系计算,这样就加速后期的重用。
在这里插入图片描述

  • 分区: 把任务分成子任务并行运算 ; 数据不一样但是计算逻辑一样

在这里插入图片描述

RDD属性

  • 分区的列表
  • 每个分区的计算函数
  • RDD的依赖关系 getDenpencies
  • 分区器 partitioner : 分区的规则
  • 分区选择器: 任务分发的首选位置(哪个节点的效率最优),移动数据不如移动计算

调度池

在这里插入图片描述

Stage划分

各个RDD的依赖关系生成了G,通过DAG来划分

如何划分呢?

在DAG中进行反向解析,遇到宽依赖就断开,遇到窄依赖就把当前的RDD加入到当前的阶段中,将窄依赖尽量划分在同一个阶段中可以实现流水线计算

RDD运行流程

  1. 创建RDD对象,RDD对象
  2. 根据RDD对象之间的依赖关系形成DAG图
  3. DAG图由DAGScheduler拆解成各个阶段,各阶段内的任务由TaskScheduler分发到WorkNode中的Executor执行

部署方式

Standalone模式(集群模式):

Spark框架自带完整的资源调度管理服务,可以独立的部署到一个集群中,不需要其他系统

Spark on Mesos:

Mesos是一个资源调度框架,比Yarn更灵活

Spark on Yarn:

资源管理和调度依赖YARN,分布式存储依赖HDFS

Spark编程

  • 创建RDD

parallelize 和 makeRDD

val rdd = sc.parallelize(Array(1,2,3,4,5,6,7,8))

差异:makeRDD底层调用的是parallelize方法 ,makeRDD更好理解

makeRDD方法可指定并行分区数,默认为CPU最大的核数
  • 读取文件:
    textFile(path)

    • path既可以是文件路径也可以是目录路径(读取目录中所有的文件)
    • 都是字符串类型

    wholeTextFiles() : 以文件为单位读取数据,元组的形式(path,text)

output文件:

  • crc是校验文件
  • _SUCCESS 状态文件

数据是如何分配数据分区的?

数据如何切分?
len=5, partitionNum=3

for i 0 until partitionNum:
	start = i * len / paratitionNum 
	end = (i+1) * len / paratitionNum 
	(start, end)

文件分区分配:

  1. spark读取文件是按照hadoop的方式读取的,按行读取 ,和字节数没有关系

    totalsize / ParatitionNum
    大于10% ,产生新的分区

    7 / 3 = 2 …1 > 1.1
    所以 ParatitionNum = 2 + 1

  2. 数据读取时以偏移量为单位

  3. 数据分区的偏移量的范围计算(以偏移量为3为单位)
    0 => [0,3]
    1 => [3,6]

map()和 mapPartition()的区别

  1. map():每次处理一条数据。
  2. mapPartition():每次处理一个分区的数据,这个分区的数据处理完后,原 RDD 中分区的
    数据才能释放,可能导致 OOM。
  3. 开发指导:当内存空间较大的时候建议使用 mapPartition(),以提高处理效率。

glom

作用:将每一个分区形成一个数组,形成新的 RDD 类型时 RDD[Array[T]]

groupBy(func)

  1. 作用:分组,按照传入函数的返回值进行分组。将相同的 key 对应的值放入一个迭代
    器。

filter(func)

  1. 作用:过滤。返回一个新的 RDD,该 RDD 由经过 func 函数计算后返回值为 true 的输入元素组成。

sample(withReplacement, fraction, seed)

  1. 作用:以指定的随机种子随机抽样出数量为 fraction 的数据,withReplacement 表示是抽出的数据是否放回,true 为有放回的抽样,false 为无放回的抽样,seed 用于指定随机数生成器种子。

distinct([numTasks]))

  1. 作用:对源 RDD 进行去重后返回一个新的 RDD。默认情况下,只有 8 个并行任务来操作,但是可以传入一个可选的 numTasks 参数改变它。

sortBy(func,[ascending], [numTasks])

  1. 作用;使用 func 先对数据进行处理,按照处理后的数据比较结果排序,默认为正序。

pipe(command, [envVars])

  1. 作用:管道,针对每个分区,都执行一个 shell 脚本,返回输出的 RDD

RDD Key-Value类型

Spark 目前支持 Hash 分区和 Range 分区,Hash 分区为当前的默认分区,Spark 中分区器直接决定了 RDD 中分区的个数、RDD 中每条数据经过Shuffle 过程属于哪个分区和 Reduce 的个数

注意:
(1)只有 Key-Value 类型的 RDD 才有分区的,非 Key-Value 类型的 RDD 分区的值是 None
(2)每个 RDD 的分区 ID 范围:0~numPartitions-1,决定这个值是属于那个分区的。

数据格式是(key,value)类型

哈希分区

HashPartitioner 分区的原理:对于给定的 key,计算其 hashCode,并除以分区的个数取余,如果余数小于 0,则用余数+分区的个数(否则加 0),最后返回的值就是这个 key 所属的分区 ID。

mapPartitionsWithIndex
  1. map函数是一条数据一条数据的处理,也就是,map的输入参数中要包含一条数据以及其他你需要传的参数。

  2. mapPartitions函数是一个partition数据一起处理,也即是说,mapPartitions函数的输入是一个partition的所有数据构成的“迭代器”,然后函数里面可以一条一条的处理,在把所有结果,按迭代器输出。也可以结合yield使用效果更优。

  3. mapPartitionsWithIndex函数,其实和mapPartitions函数区别不大,因为mapPartitions背后调的就是mapPartitionsWithIndex函数,只是一个参数被close了。mapPartitionsWithIndex的函数可以或得partition索引号;

partitionBy

  1. 作用:对 pairRDD 进行分区操作,如果原有的 partionRDD 和现有的 partionRDD 是一致的话就不进行分区, 否则会生成 ShuffleRDD,即会产生 shuffle 过程。

reduceByKey(func, [numTasks])

  1. 在一个(K,V)的 RDD 上调用,返回一个(K,V)的 RDD,使用指定的 reduce 函数,将相同key 的值聚合到一起,reduce 任务的个数可以通过第二个可选的参数来设置
reduceByKey 和 groupByKey 的区别
  1. reduceByKey:按照 key 进行聚合,在 shuffle 之前有 combine(预聚合)操作,返回结果是 RDD[k,v]。
  2. groupByKey:按照 key 进行分组,直接进行 shuffle。
  3. 开发指导:reduceByKey 比 groupByKey,建议使用。但是需要注意是否会影响业务逻辑

SparkSQL

Spark SQL 是 Spark 用来处理结构化数据的一个模块,它提供了 2 个编程抽象:DataFrame 和 DataSet,并且作为分布式 SQL 查询引擎的作用。

与 RDD 类似,DataFrame 也是一个分布式数据容器。然而 DataFrame 更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即 schema。

Dataframe 是 Dataset 的特列,DataFrame=Dataset[Row] ,所以可以通过 as 方法将 Dataframe转换为 Dataset。Row 是一个类型,跟 Car、Person 这些的类型一样,所有的表结构信息我都用 Row
来表示。

peisist()

RDD 通过 persist 方法或 cache 方法可以将前面的计算结果缓存,默认情况下 persist() 会把数据以序列化的形式缓存在 JVM 的堆空间中。
但是并不是这两个方法被调用时立即缓存,而是触发后面的 action 时,该 RDD 将会被缓存在计算节点的内存中,并供后面重用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值