SparkCore的学习

一、RDD 详解

RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,代表一个不可变、可分区、里面的元素可并行计算的集合。

1.1 RDD的五大特性

1.RDD是有分区的; 2.RDD的方法会作用在其所有分区上; 3.RDD之间可以进行迭代计算(存在依赖关系);
4.k-v型RDD可以有分区器(但是不是所有的RDD都是kv型); 5.RDD的分区规划,会尽量靠近数据所在的服务器;

二、RDD编程

2.1 RDD的创建

常用的api 详见如下代码:

from pyspark import SparkConf,SparkContext
if __name__ == '__main__':
# 构建SparkConf对象
conf = SparkConf().setAppName("test").setMaster("local[*]")
# 构建SparkContext执行环境入口对象
sc = SparkContext(conf = conf)
# 将本地集合转化成rdd对象
# data = [1,2,3,4,5,6,7,8,9]
# rdd = sc.parallelize(data,3)
# textFile可以读取本地数据或者hdfs数据,参数一:必填,文件路径,参数二:可选,设置最小分区数,并且在允许范围内参数2才有作用
# rdd = sc.textFile("/opt/sofetware/word.txt",4)
# 适合读取一堆小文件,参数设置同textFile基本一致
rdd = sc.wholeTextFiles("/opt/sofetware/word.txt",4)
# 获取rdd的分区数量
print(rdd.getNumPartitions())
print(rdd.collect())

2.2 RDD算子

2.2.1 定义

算子: 分布式集合对象上的API称之为算子;
方法(函数): 本地对象的API叫做方法(函数);

2.2.2 算子的分类

RDD的算子分为两类:转换算子和动作算子;
Transformation算子返回值仍旧是一个RDD的称之为转换算子;
action算子返回值不是RDD的就是动作算子;

2.2.3 常用的Transformation算子

1.map()算子根据参数中的函数将RDD的数据一条条处理,并返回一个新的rdd;
2.flatmap()算子对rdd对象进行map操作,然后执行解除嵌套操作;
3.reduceByKey()算子针对kv型rdd,自动按照key分组,根据你设置的聚合逻辑,完成组内数据的聚合工作。注意:reduceByKey接受的函数只负责聚合逻辑;
4.mapValues()算子针对二元元组rdd,对其内部的二元元组的value执行map操作;
5.groupBy()算子将rdd的数据进行分组;
6.Filter()算子过滤想要的数据进行保留(返回值为true或false,为true保留该数据,false就过滤掉);
7.distinct()算子对rdd数据进行去重,返回新的rdd(参数可以加上去重分区数量,也可以不加参数);
8.union()算子两个rdd合并成一个rdd返回(注意该算子只会合并不会去重,不同类型的rdd也可以合并);
9.join()算子对两个rdd执行关联操作(可实现sql的内外连接 leftOuterJoin 和 rightOuterJoin ),join算子只能用于二元元组,即KV类型的rdd,而且自动只对key进行关联,如需对value进行关联,需要自行将key和value位置调换;
10.intersection()算子返回两个rdd的交集;
11.glom()算子将rdd的数据加上嵌套,这个嵌套按照分区来进行;
12.groupByKey()算子针对KV类型认定的,自动按照key分组(无需输入参数);
13.sortBy()算子对rdd数据进行排序,根据你指定的排序方法(参数1是函数,告知你要排序的数据,参数2是true是升序,反之降序,参数2排序的分区数);
14.sortByKey()算子针对KV型rdd,按照key进行排序;

2.2.4 常用的action算子

1.counyByKey()算子统计key出现的次数(一般用于KV型rdd,返回字典类型数据);
2.collect()算子将rdd各个分区内的数据统一收集到driver中,形成一个list对象(注意不能用于太大的数据,会把driver内存撑爆);
3.reduce()算子对rdd数据集按照你传入的逻辑进行聚合;
4.fold()算子接受传入逻辑进行聚合,和reduce很像,只不过这种聚合是带有初始值的,这种聚合会作用在分区内和分区间;
5.first()算子取出rdd的第一个元素;
6.take()算子取rdd的前n个元素,组合成list并返回;
7.top()算子对rdd数据进行降序排序,取前n个;
8.count()算子计算rdd有多少条数据,并返回一个数字;
9.takeSample()算子随机抽样rdd的数据(参数1,表示是否允许取相同的数据,参数2,取数据的个数,参数3,随机数种子,非必选);
10.takeOrdered()算子对rdd进行排序取前n个(参数1,数据个数,参数2,对数据进行处理,默认升序,参数2非必选);
11.foreach()算子对rdd的每一个数据执行你所提供的操作,该算子没有返回值;
12.saveAsTextFile()算子将rdd的数据写入文本文件中,支持本地、hdfs等文件写出;
注意foreach和saveAsTextFile这两个算子都是分区直接执行的,跳过driver,其余的action算子都会把结果发送到driver;

2.2.5 分区操作算子

1.mapPartitions()算子相比map来说,该算子依次传输的是整个分区的数据,作为一个迭代器传输过来;
2.foreachPartition()算子相比普通foreach,该算子依次处理的是整个分区的数据,foreachPartition就是一个没有返回值的mapPatitions;
3.coalesce()算子对分区进行数量增减(参数1,分区数,参数2,是否允许shuffle,默认false,增加分区需要将参数2改为true,非必选);
3.partitionBy()算子对rdd进行自定义分区操作(参数1,分区的个数,参数2,分区规则的函数);
4.repartiton()算子对rdd的分区执行重新分区(仅数量,使用一定要慎重);

三、RDD的持久化

1.RDD的数据是过程数据。RDD之间进行相互迭代计算,当新的RDD生成后,旧的RDD就消失了,只在处理的过程中存在,一旦处理完成后就不存在了。这个特性可以最大化的利用资源。
2.RDD缓存。 Spark提供了缓存API,将指定的rdd数据持久化保留在内存或磁盘上。但是缓存在设计上是不安全的,存在丢失风险,所以缓存会保留rdd之间的依赖关系。而且缓存是分散存储的。

3.RDD的checkPoint。 checkPoint也可以保存数据,但是它仅支持保存到硬盘上,是集中存储数据,不保留rdd的依赖关系,checkPoint被认为是安全的。
checkPoint适合重量级的使用,当计算成本较大或数据量较大时比较适合使用checkPoint,如果数据量小或者数据不是很重要就直接使用rdd缓存就可以了。


4.使用方法:

sc.setCheckpointDir("保存路径")
#用的时候直接调用
rdd.checkpoint()

四、共享变量

4.1 广播变量

使用广播变量后,每个Executor只会收到一份这样的广播变量,内部的各个线程(分区)共享这一个广播变量,而不是每一个分区都发送一份(造成内存浪费),使用广播变量可以节省内存。
使用场景本机集合变量需要和分布式集合对象rdd进行关联的时候,需要将本地集合对象封装成广播变量,这样可以节省网络IO次数和executor的内存占用。而且只适用于本地集合变量数据不是很大的情况,如果本地集合数据量大的话,更适合将本地集合转化成rdd对象。
使用方法:

#将list标记为广播变量
broadcast = sc.broadcast(list)

4.2 累加器

作用是得到全部数据计算后的累加结果,它可以从各个Executor中收集执行结果作用到自己身上。使用累加器时要注意避免调用已被销毁的rdd对象,否则会使数据不准确。
构建方法sc.accumulator(初始值)

五、Spark内核调度

5.1 DAG

DAG有方向没有形成闭环的一个执行流程图,作用是标识代码的逻辑执行流程。
一个action会产生一个DAG,一个DAG会产生一个job。所以一个application中可以有多个job,每一个job内含一个DAG,同时每一个job都是由一个action产生的。

5.2 DAG的宽窄依赖和阶段划分

宽依赖父rdd的一个分区,全部将数据发给子rdd的一个分区(宽依赖还有一个别名:shuffle);
窄依赖父rdd的一个分区,将数据发给子rdd的多个分区;
阶段划分对Spark来说会根据DAG的宽窄依赖划分不同的DAG阶段,划分依据是:从后向前开始,遇到一个宽依赖就划分出一个阶段,称之为stage,所以在stage的内部一定都是窄依赖。

5.3 内存迭代计算

5.4 Spark并行度

spark的并行同一时间内有多少个task在同时运行,并行度即并行能力的设置。
spark的并行度可以在运行代码、客户端或者配置文件中来设置,全局并行度配置的参数为:spark.default.parallelism,该参数默认为1,但是不会全部以这个数值来运行,多数时候基于读取文件的分片数量来作为默认并行度。
并行度的配置方法:
1.配置文件中在路径conf/spark-default.conf中设置spark.default.parallelism参数数值;
2.在客户端提交参数中:使用命令 bin/spark-submit --conf "spark.default.parallelism=10",一般建议并行度是cpu总核心的2~10倍,并且不建议针对rdd修改分区;
3.也可以在代码中设置

conf = SparkConf()
conf.set("spark.default.parallelism","10")

5.5 Spark的任务调度

driver内的两个组件
1.DAG调度器将逻辑的DAG图进行处理最终得到逻辑上的task划分;
2.Task调度器基于DAG的调度来规划这些逻辑的task应该在哪些executor上运行并监控其工作;

5.6 Spark层级关系梳理

posted @   KongLong_cm  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示