spark四种运行模式:
local Mode本地模式
Standalone集群模式(伪分布式模式)
Spark on Yarn 模式:
分为两种方式:Spark Client模式和Spark cluster模式
mr-jobhistory-daemon.sh start historyserver yarn的历史服务器(HistoryServer)
/export/server/spark/sbin/start-history-server.sh spark的历史服务器(JobHistoryServer)
client和cluster的区别:client模式下,程序运行在提交的节点,cluster模式下,程序运行在yarn集群上 选择cluster较好
注意:Spark-Shell和Spark-submit
shell:Spark的应用交互窗口,启动后可编写Spark代码,一般测试使用
Submit:用来将spark任务的jar包提交到spark集群上
Cloud 云模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qRjTyZzQ-1651804598404)(C:\Users\阿萨姆\AppData\Roaming\Typora\typora-user-images\image-20220421090857037.png)]
spark的角色介绍:
Driver Program:运行main函数并且新建SparkContext的程序。
Application:基于Spark的应用程序,包含了driver程序和集群上的executor。
Cluster Manager:指的是在集群上获取资源的外部服务。目前有三种类型
(1)Standalone:Spark原生的资源管理,由Master负责资源的分配
(2)Apache Mesos:与Hadoop mr兼容性良好的一种资源调度框架
(3)Hadoop Yarn:主要是指Yarn中的ResourceManager
Worker Node:集群中任何可以运行Application代码的节点,在Standalone模式中指定的是通过slaves文件配置的Worker节点,在Spark on Yarn模式下就是NodeManager节点
Executor:是一个Worker Node上为某应用启动的一个进程,该进程负责运行任务,并且负责将数据存在内存或者磁盘上。每个应用都有各自独立的executor。
Task:被送到某个executor上的工作单元
RDD的五大特性:
1.a list of partitions 每个RDD由一系列的分区组成,也就是说一个RDD中有多个分区(分片)
2.A function for computing each split 一个函数计算一个分片的数据 可并行计算,每个分片的数据应用 函数进行处理
3.A list of dependencies on other RDDs 一个RDD 依赖一系列的RDD
4.RDD是由(key,value)二元组组成的,可设置分区器
5.对RDD中每个分区的数据进行处理时,找到最佳位置列表
RDD的操作
Transformation转换操作:返回新的RDD
Action动作操作:不返回新的RDD 或者 不返回RDD 或者不返回
MapPartition和Map
val data: RDD[String] = sc.textFile("data/input/wordcount.data")
val result: RDD[(String, Int)] = data
.filter(StringUtils.isNoneBlank(_))
.flatMap(_.split("\\s+"))
//这个map函数处理对象是整个RDD
//*.map((_, 1))*/
//而相比于map函数 此函数作用对象是每个分区
.mapPartitions(item =>{
item .map((_,1))
})
.reduceByKey(_ + _)
一般使用map即可 但有的特殊情况要使用mappartition 比如:开启连接和关闭连接,mappartition有几个分区就执行几次 而map函数是由多少数据就执行多少次
foreach和foreachpartition
//result.foreach(println)
result.foreachPartition(item =>{
item.foreach(println)
})
一般使用foreach即可 但有的特殊情况要使用oreachpartition 比如:开启连接和关闭连接,oreachpartition有几个分区就执行几次 而foreach函数是由多少数据就执行多少次,将数据写入数据库 使用foreachpartition
GroupByKey+Sum和ReduceByKey
GroupByKey +Sum 先分组再聚合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nD2g9WkS-1651804598406)(C:\Users\阿萨姆\AppData\Roaming\Typora\typora-user-images\image-20220422172009772.png)]
ReduceByKey先预聚合 再分组 再局部聚合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jjWaNw9m-1651804598406)(C:\Users\阿萨姆\AppData\Roaming\Typora\typora-user-images\image-20220422172136856.png)]
性能上ReduceByKey更好一点
排序:
SortBy
SortByKey
top
第一种 sortby()
val result: Array[(String, Int)] = data
.filter(StringUtils.isNotBlank(_))
.flatMap(_.split("\\s+"))
.map((_, 1))
.reduceByKey(_ + _)
// .sortByKey()//按key进行默认升序排序
.sortBy(_._2, false)//按照元组中第二个元素进行排序 第二个参数是指升序还是降序
.take(3)
第二种:元组交换 swap 和 take(有在数据量很小的情况下使用 所有的数据都被加载在驱动程序的内存中)
val result: Array[(Int, String)] = data
.filter(StringUtils.isNotBlank(_))
.flatMap(_.split("\\s+"))
.map((_, 1))
.reduceByKey(_ + _)
.map(_.swap)
.sortByKey(true)
.take(3)
第三种:top(只有在数据量很小的情况下使用 所有的数据都被加载在driver存储器中)
val result = data
.filter(StringUtils.isNotBlank(_))
.flatMap(_.split("\\s+"))
.map((_, 1))
.reduceByKey(_ + _)
.top(3)(Ordering.by(_._2))
result.foreach(println)
RDD的持久化和缓存
缓存解决什么问题?解决热点问题频繁访问的效率问题
RDD转换和计算需要消耗时间,如果RDD后续还需要用到的话,可以将RDD进行缓存,下一次可以直接调用缓存的RDD,提高了效率
缓存的RDD存放到计算节点的内存中
persist()默认存储级别MEMORY_ONLY
一般使用MEMORY_AND_DISK
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xivnIug4-1651804598406)(C:\Users\阿萨姆\AppData\Roaming\Typora\typora-user-images\image-20220422200047658.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Xg2xVsx-1651804598407)(C:\Users\阿萨姆\AppData\Roaming\Typora\typora-user-images\image-20220422200030102.png)]
CheckPoint
RDD的数据可以持久化到内存中,但是不是最可靠的,内存不够可以存放在磁盘上,但是磁盘损坏一样导致数据丢失。最可靠的就是将RDD数据缓存到hdfs上,
Checkpoint就是为了数据的更可靠的持久化而产生的。实现RDD的高容错和高可用
设置checkpoint的步骤:
1先设置checkpoint的路径
2将rdd放入checkpoint中
3.直接使用RDD即可 RDD会从缓存中自动加载
4.使用完RDD后清除缓存
def main(args: Array[String]): Unit = {
//TODO 创建环境
val sc = {
val SparkConf = new SparkConf()
.setAppName(this.getClass.getSimpleName.stripPrefix("$"))
.setMaster("local[*]")
new SparkContext(SparkConf)
}
//TODO 采集数据
val data: RDD[String] = sc.textFile("data/input/wordcount.data")
val result: RDD[(String, Int)] = data
.filter(StringUtils.isNotBlank(_))
.flatMap(_.split("\\s+"))
.map((_, 1))
//应为result会被频繁使用,且该RDD需要进行计算和转换,将result=>RDD放到缓存中,加快效率
result.persist(StorageLevel.MEMORY_AND_DISK)
//构建checkpoint目录
sc.setCheckpointDir("./ckpt")
//将rdd放入checkpoint中(自己创建)
result.checkpoint();
//自动取出
result.reduceByKey(_ + _).foreach(println)
//使用完清除缓存
result.unpersist()
//关闭配置
sc.stop()
}
checkpoint和RDD持久化缓存的区别
存储位置:
RDD持久化缓存:默认存放在内存中,内存不够存放在磁盘上
checkpoint存放在HDFS上
功能:
RDD持久化:保证RDD数据后续被使用的效率变高
CheckPoint:保证数据的安全性 一定程度上也可以加快效率:(反正是比重新计算更快)
累加器 广播变量
广播变量 Broadcast Variables
广播变量用来把变量所在的节点的内存之间进行共享,每个机器上缓存一个只读变量
将变量广播到每一台机器上 不需要广播到每一个task上
累加器 Accumulations
累加器支持不同节点之间的累加操作
Spark Core 读写Mysql数据
//写数据
val sc: SparkContext = {
new SparkContext(new SparkConf