目录
01:上次回顾
https://blog.csdn.net/m0_57498038/article/details/119103534
-
SparkCore代码的开发流程是什么?
//step1:构建SparkContext对象:读取数据,Task解析、分配、监控 val conf = new SparkConf .set(key,value) .setMaster .setAppName val sc = new SparkContext / val sc = SparkContext.getOrCreate //step2:实现程序的处理逻辑:读取、转换、保存 val rdd1 = sc.textFile val rddN = rdd1.t1.t2.t3…… rddN.save //step3:释放资源:sc sc.stop
-
如何使用spark-submit脚本提交运行jar包?
-
脚本:spark-submit
-
语法:spark-submit 选项 jar包 args
-
选项
-
基本选项
-
--master:local【K】、spark://node1:7077、yarn
-
--class
-
--deploy-mode
-
--jars
-
--conf
-
--name
-
-
资源选项
-
driver
-
--dirver-memory
-
--driver-cores
-
-
executor
-
--executor-memory
-
--executor-cores
-
YARN:--num-executors
-
Standalone:--total-executor-cores
-
-
-
-
-
什么是deploymode?Spark on YARN时,client与cluster有什么区别?
-
功能:决定了driver进程运行的位置
-
选项
-
client:默认选项,driver进程运行在客户端上
-
cluster:driver进程运行在Worker节点上
-
-
Spark on YARN
-
client:driver和APPMaster是共存的
-
APPMaster:申请资源,启动Executor
-
NodeManager
-
-
Driver:管理所有Executor、解析、分配、监控Task
-
Client
-
-
-
cluster:driver和APPMaster,整体由统一的进程来实现
-
-
-
什么是RDD?
-
定义:弹性分布式数据集合,具有高容错性能实现数据分布式存储的数据集合
-
特点
-
分布式:能实现并行化的处理操作
-
高容错:血脉
-
-
-
RDD的五大特性是什么?
-
每个RDD都由多个分区构成
-
对RDD的操作,实际上在物理中对每个分区的操作
-
每个RDD保留与其他RDD之间的依赖关系:通过父RDD怎么得到子RDD
-
可选:对于二元组KV结构的RDD,在经过Shuffle的时候,可以自定义指定分区器
-
Spark自带的分区器:Hash分区、范围分区
-
-
可选:在Task分配计算时,可以计算最优路径解
-
-
反馈问题
-
Driver是master开启的吗?
-
不是:Driver是客户端启动的
-
-
sortBy在scale中只有升序没有降序,而在spark的RDD中,sortBy却可以降序,用的不是原Scala的方法了,这样出现的方法名重复的情况要怎么解释呢?
-
02:学习目标
-
RDD的构建
-
构建的两种方式
-
-
==RDD的算子==
-
算子分类:触发算子、转换算子
-
==常用算子:基本算子、分区操作、重分区、聚合、二元组函数xxxxByKey、关联函数==
-
-
RDD的容错机制
-
函数:persist、cache、checkpoint
-
问题1:RDD通过什么方式来保证数据安全?
-
血链
-
-
问题2:RDD每触发使用一次,就需要构建一次血链,性能比较差?
-
缓存
-
-
问题3:缓存如果丢失怎么办?
-
持久化
-
-
-
搜狗日志分析案例
-
练习在实际业务场景下:怎么利用RDD的算子来解决业务需求
-
03:RDD的创建
-
目标:掌握Spark程序中的RDD如何创建
-
实施
There are two ways to create RDDs: parallelizing an existing collection in your driver program, or referencing a dataset in an external storage system, such as a shared filesystem, HDFS, HBase, or any data source offering a Hadoop InputFormat.
-
方式一:并行化一个已存在的集合
val seq: immutable.Seq[Int] = 1.to(10) val rdd1: RDD[Int] = sc.parallelize(seq)
-
parallelize / makeRDD【允许构建最优路径】:并行化一个集合变成一个RDD
-
-
方式二:读取外部数据源构建RDD
//读取外部文件系统 val rdd2: RDD[String] = sc.textFile("datas/wordcount") //调用Hadoop中任意一种输入类,将输入类的结果构建RDD val rdd3 = sc.newAPIHadoopRDD("调用Hadoop中哪个输入类","返回Key类型","返回Value类型")
-
-
小结
-
RDD的创建方式有几种?
-
并行化集合
-
读取外部存储系统
-
-
04:RDD的分区
-
目标:掌握如何管理RDD的分区个数
-
实施
-
分区个数指定
-
构建RDD时,可以指定分区个数
//并行化集合指定分区个数 val seq: Seq[Int] = 1.to(10) val seqRdd: RDD[Int] = sc.parallelize(seq,numSlices = 3) //读取外部系统指定分区个数 val inputRdd = sc.textFile("datas/wordcount",minPartitions = 3)
-
指定分区的原则
-
RDD的分区个数决定了Task的个数,决定了并行度
-
原则:RDD的分区个数一般为Executor的CPU核数的2 ~ 3倍
-
举例:10个Executor,每个Executor分配4coreCPU
-
RDD的分区数的最大范围:80 ~ 120分区
-
-
-
常见的分区个数的规则
-
级别
-
默认:线程数,如果底层读取的是分布式系统
-
自定义:指定分区个数
-
-
分布式系统:实现1:1的分区关系
-
读HDFS文件:文件的一个块就自动对应RDD的一个分区
-
读Hbase表:表的一个region自动对应RDD的一个分区
-
-
问题:如果RDD是通过另外一个RDD得到的,分区个数是多少?
-
子RDD分区个数沿用父RDD的分区个数
-
-
工作中:一般读取的都是分布式系统,一般都用默认的即可
-
-
小文件合并读取
//小文件读取 //有100个分区,文件中每一条数据作为一个元素 val rdd3: RDD[String] = sc.textFile("datas/ratings100") //每个文件作为一个KV对,存储在RDD中 val rdd4: RDD[(String, String)] = sc.wholeTextFiles("datas/ratings100") rdd4.take(1).foreach(tuple => println(tuple._1+"---------"+tuple._2))
-
-
分区个数查看
//获取当前RDD的分区个数 val partitions = seqRdd.getNumPartitions //获取当前数据对应的分区编号 TaskContext.getPartitionId()
-
-
小结
-
如何指定分区个数?
-
在构建RDD时,传递分区个数参数
-
-
小文件过多,分区数太多怎么办?
-
合并读取:wholeTextFile
-
-
怎么查看分区个数和分区编号?
-
getNumPartitions
-
TaskContext.getPartitionId
-
-
05:RDD的算子分类
-
目标:掌握SparkCore中RDD算子的分类
-
路径
-
step1:问题
-
step2:转换算子
-
step3:触发算子
-
-
实施
-
问题
-
开发Spark程序时,有的代码会触发程序的job的运行,有的代码不触发job的运行?
-
设计:读取、转换RDD时,代码是不会触发Task的运行,设计Lazy的模式
-
如果执行了Task,给RDD赋值,但是这个RDD的数据没有被使用,导致数据占用内存,浪费资源
-
如果用到数据的时候,再进行对RDD赋值
-
-
问题:什么操作会触发job,什么操作不触发job?
-
转换算子:不触发job运行
-
触发算子:会触发job运行,肯定要使用RDD的数据
-
-
-
转换算子:Transformation
-
功能:实现RDD的转换操作,不会产生job,触发Task的运行
-
特点
-
返回值是一个新的RDD
-
不会触发job的运行,都是lazy模式的
-
-
常见算子
-
map
-
-
flatMap
-
sortBy/sortByKey:特例,经过shuffle的算子,使用RangePartition,做数据采样,会读取数据,触发Job去读取数据
-
filter
-
reduceByKey
-
……
-
-
-
-
触发算子:Action
-
-
功能:实现RDD数据的读取操作,会触发job的运行,构建RDD的数据
-
特点
-
触发job的运行,构建Task,实现物理上的RDD的数据读取、转换
-
-
返回值不为RDD类型,为普通类型或者为空
-
-
常见算子
-
foreach:没有返回值,打印输出
-
collect:将RDD每个分区的数据放入一个数组中,返回
-
reduce:聚合函数,返回聚合后的结果
-
fold:聚合函数,返回聚合后的结果
-
count:统计元素的个数返回
-
saveAsTextFile:没有返回值,保存数据到外部文件系统
-
……
-
-
-
-
小结
-
RDD的算子分为几类,有什么区别?
-
转换算子:Transformation
-
不会触发job和Task的运行,是Lazy模式,只定义转换逻辑
-
返回值为RDD类型
-
-
触发算子:Action
-
会触发job和Task的运行,真正从物理上执行所有RDD分区数据的构建和转换
-
返回值为空或者普通类型
-
-
-
06:RDD常用算子:基础函数
-
目标:掌握Spark的RDD中常用的基础函数
-
实施
-
map
-
功能:实现对RDD中每个元素的处理,将处理的结果放入新的RDD中进行返回
-
语法
de
-
-