Spark

yarn Cluster 与yarn Client的区别:
在这里插入图片描述

S p a r k 的 资 源 管 理 组 件
Yarn(通用)
– Master/Slave结构
• RM:全局资源管理器,负责系统的资源管理和分配
• NM:每个节点上的资源和任务管理器
• AM:每个应用程序都有一个,负责任务调度和监视,并与RM调度器协商为任务获取资源
Standalone(Spark自带)
– Master/Slave结构
• Master:类似Yarn中的RM
• Worker:类似Yarn中的NM

S p a r k 和 H a d o o p 作 业 之 间 的 区 别
Hadoop中:
– 一个MapReduce程序就是一个job,而一个job里面可以有一个或多个Task,Task又可以区分为Map Task和Reduce Task
– MapReduce中的每个Task分别在自己的进程中运行,当该Task运行完时,进程也就结束
在这里插入图片描述
Spark中:
– 同样有job的概念,但这里的job和MR中的job不一样
– 一个Application和一个SparkContext相关联,每个Application中可以有一个或多个job,可以并行或串行运行job
– Spark中一个Action可以触发一个job运行
– 在job里面包含多个stage,stage以shuffle进行划分,stage中包含多个Task,多个Task构成了Task Set
– 和MapReduce不一样,Spark中多个Task可以运行在一个进程
里面,而且这个进程的生命周期和Application一样,即使没有job运行
– 优点:加快Spark运行速度,Task可以快速启动,并处理内存中数据
– 缺点:每个Application拥有固定数量的executor和固定数目的内存
在这里插入图片描述
Spark中:
应用程序:由一个driver program和
多个job构成
– **Job:**由多个stage组成
Stage:对应一个taskset
Taskset:对应一组关联的相互之间没
有shuffle依赖关系的task组成
Task:任务最小的工作单元

Driver Program的功能:
– (驱动程序)是Spark的核心组件
– 构建SparkContext(Spark应用的入口,创建需要的变量,还包含集群的配置信息等)
– 将用户提交的job转换为DAG图(类似数据处理的流程图)
– 根据策略将DAG图划分为多个stage,根据分区从而生成一系列tasks
– 根据tasks要求向RM申请资源
– 提交任务并检测任务状态
Executor的功能:
– 真正执行task的单元,一个Work Node上可以有多个Executor


spark on yarn

MR有什么问题?
调度慢,启动map、reduce太耗时
计算慢,每一步都要保存中间结果落磁盘
API抽象简单,只有map和reduce两个原语
缺乏作业流描述,一项任务需要多轮mr

什么是spark?
– 也是一个分布式的并行计算框架
– spark是下一代的map-reduce,扩展了mr的数据处理流程。
– executor都是装载在container里运行,container默认内存是
1G(参数yarn.scheduler.minimum-allocation-mb定义)
– executor分配的内存是executor-memory,向YARN申请的内存是(executor-memory + 1)* num-executors。
AM在Spark中叫driver,AM向RM申请的是executor资源,当配完资源后,executor启动后,由spark的AM向executor分
配task,分配多少task、分配到哪个executor由AM决定,可理解为spark也有个调度过程,这些task都运行在executor的坑里

– Executor有线程池多线程管理这些坑内的task
在这里插入图片描述
Spark解决了什么问题?
– 最大化利用内存cache
– 中间结果放内存,加速迭代
– 某结果集放内存,加速后续查询和处理,解决运行慢的问题
– 更丰富的API
(解决API单一问题)
在这里插入图片描述
– Transfomation变换的api,比如map可对每一行做变换,filter过滤出符合条件的行等,这些API实现用户算法,灵活。
– spark提供很多转换和动作,很多基本操作如Join,GroupBy已经在RDD转换和动作中实现。不需用户自己实现

– 完整作业描述
– 将用户的整个作业穿起来。关键是这3行。可以立即解释。不像mr那样,需要实现多个map和reduce脚
本,解决MR缺乏作业流描述问题
在这里插入图片描述


Spark Core

Spark基于弹性分布式数据集(RDD)模型,具有良好的通用性、容错性与并行处理数据的能力
• RDD( Resilient Distributed Dataset ):弹性分布式数据集(相当于集合),它的本质是数据集的描述(只读的、可分区的分布式数据集),而不是数据集本身

RDD的关键特征:
– RDD使用户能够显式将计算结果保存在内存中,控制数据的划分,并使用更丰富的操作集合来处理
– 使用更丰富的操作来处理,只读(由一个RDD变换得到另一个RDD,但是不能对本身的RDD修改)
– 记录数据的变换而不是数据本身保证容错(lineage)
• 通常在不同机器上备份数据或者记录数据更新的方式完成容错,但这种对任务密集型任务代价很高
• RDD采用数据应用变换(map,filter,join),若部分数据丢失,RDD拥有足够的信息得知这部分数据是如何计算得到的,可通过重新计算来得到丢失的数据
• 这种恢复数据方法很快,无需大量数据复制操作,可以认为Spark是基于RDD模型的系统
– 懒操作,延迟计算,action的时候才操作
– 瞬时性,用时才产生,用完就释放

Spark允许从以下四个方面构建RDD
– 从共享文件系统中获取,如从HDFS中读数据构建RDD
• val a = sc.textFile(“/xxx/yyy/file”)
– 通过现有RDD转换得到
• val b = a.map(x => (x, 1))
– 定义一个scala数组
• val c = sc.parallelize(1 to 10, 1)
– 有一个已经存在的RDD通过持久化操作生成
• val d = a.persist(), a. saveAsHadoopFile(“/xxx/yyy/zzz”

Spark针对RDD提供两类操作:transformations和action
transformations是RDD之间的变换,action会对数据执行一定的操作
– transformations采用懒策略仅在对相关RDD进行action提交时才触发计算

每个RDD包含了数据分块/分区(partition)的集合,每个partition是不可分割的
– 实际数据块的描述(实际数据到底存在哪,或者不存在)
– 其值依赖于哪些partition

与父RDD的依赖关系(rddA=>rddB)
– 宽依赖: B的每个partition依赖于A的所有partition
• 比如groupByKey、reduceByKey、join……,由A产生B时会先对A做shuffle分桶
– 窄依赖: B的每个partition依赖于A的常数个partition
• 比如map、filter、union……
在这里插入图片描述

RDD依赖关系
• 每个partition的计算就是一个task,task是调度的基本单位
• 若一个stage包含的其他stage中的任务已经全部完成,这个stage中的任务才会被加入调度
• 遵循数据局部性原则,使得数据传输代价最小
– 如果一个任务需要的数据在某个节点的内存中,这个任务就会被分配至那个节点
– 需要的数据在某个节点的文件系统中,就分配至那个节点(此时的调度指的是:由spark的AM来决定计算partition的task,分配到哪个executor上)

— 容 错
• 如果此task失败,AM会重新分配task
• 如果task依赖的上层partition数据已经失效了,会先将其依赖的partition计算任务再重算一遍
• 宽依赖中被依赖partition,可以将数据保存HDFS,以便快速重构(checkpoint)
– 窄依赖只依赖上层一个partition,恢复代价较少;宽依赖依赖上层所有partition,如果数据丢失,上层所有partiton要重算
• 可以指定保存一个RDD的数据至节点的cache中,如果内存不够,会LRU释放一部分,仍有重构的可能


Spark 调优

S p a r k 作业运行原理
在这里插入图片描述

S p a r k 资源参数调优

• Executor的内存分为3块
• 第一块:让task执行代码时,默认占executor总内存的20%
• 第二块:task通过shuffle过程拉取上一个stage的task的输出后,进行聚合等操作时使用,默认也是占20%
• 第三块:让RDD持久化时使用,默认占executor总内存的60%
• Task的执行速度和每个executor进程的CPU Core数量有直接关系,一个CPU Core同一时间只能执行一个线程,每个executor进程上分配到的多个task,都是以task一条线程的
方式,多线程并发运行的。如果CPU Core数量比较充足,而且分配到的task数量比较合理,那么可以比较快速和高效地执行完这些task线程

num-executors:该作业总共需要多少executor进程执行
– 建议:每个作业运行一般设置50~100个左右较合适
executor-memory:设置每个executor进程的内存, num-executors* numexecutors代表作业申请的总内存量(尽量不要超过最大总内存的1/3~1/2)
– 建议:设置4G~8G较合适
executor-cores:每个executor进程的CPU Core数量,该参数决定每个executor进程并行执行task线程的能力, num-executors* executor-cores代表
作业申请总CPU core数(不要超过总CPU Core的1/3~1/2 )
– 建议:设置2~4个较合适
driver-memory:设置Driver进程的内存
– 建议:通常不用设置,一般1G就够了,若出现使用collect算子将RDD数据全部拉取到Driver上处理,就必须确保该值足够大,否则OOM内存溢出
spark.default.parallelism:每个stage的默认task数量
– 建议:设置500~1000较合适,默认一个HDFS的block对应一个task,Spark默认值偏少,这样导致不能充分利
用资源
spark.storage.memoryFraction:设置RDD持久化数据在executor内存中能占的比例,默认0.6,即默认executor 60%的内存可以保存持久化RDD数据
– 建议:若有较多的持久化操作,可以设置高些,超出内存的会频繁gc导致运行缓慢
spark.shuffle.memoryFraction:聚合操作占executor内存的比例,默认0.2
– 建议:若持久化操作较少,但shuffle较多时,可以降低持久化内存占比,提高shuffle操作内存占比

S p a r k 开发调 优
原则一:避免创建重复的RDD
– 对同一份数据,只应该创建一个RDD,不能创建多个RDD来代表同一份数据
– 极大浪费内存
• 原则二:尽可能复用同一个RDD
– 比如:一个RDD数据格式是key-value,另一个是单独value类型,这两个RDD的value部分完全一样,这样可以复用达到减少算子执行次数
• 原则三:对多次使用的RDD进行持久化处理
– 每次对一个RDD执行一个算子操作时,都会重新从源头处理计算一遍,计算出那个RDD出来,然后进一步操作,这种方式性能很差
– 对多次使用的RDD进行持久化,将RDD的数据保存在内存或磁盘中,避免重复劳动
– 借助cache()和persist()方法
在这里插入图片描述

• 原则四:避免使用shuffle类算子
– 在spark作业运行过程中,最消耗性能的地方就是shuffle过程
– 将分布在集群中多个节点上的同一个key,拉取到同一个节点上,进行聚合和join处理,比如
groupByKey、reduceByKey、join等算子,都会触发shuffle

原则五:使用map-side预聚合的shuffle操作
– 一定要使用shuffle的,无法用map类算子替代的,那么尽量使用map-site预聚合的算子
– 思想类似MapReduce中的Combiner
– 可能的情况下使用reduceByKey或aggregateByKey算子替代groupByKey算子,因为reduceByKey或aggregateByKey算子会使用用户自定义的函数对每个节点本地相同的key进行
预聚合,而groupByKey算子不会预聚合

• 原则六:使用Kryo优化序列化性能
– Kryo是一个序列化类库,来优化序列化和反序列化性能
– Spark默认使用Java序列化机制(ObjectOutputStream/ ObjectInputStream API)进行序列化和反序列化
– Spark支持使用Kryo序列化库,性能比Java序列化库高很多,10倍左右

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值