学习spark过程中的一些个人总结

spark是一个与Hadoop数据兼容的快速通用处理引擎。

它可以通过集群或spark的独立模式在Hadoop集群中运行特点:
1、速度快:ApacheSPark使用最新的DAG调度程序、查询优化器和物理执行引擎(基于内存处理数据),实现了批处理和流数据的高性能
2、易用性:Spark支持Java、Python和Scala的API,还支持超过80种高级算法,使用户可以快速构建不同的应用。
3、通性用:Spark提供了统一的解决方案。Spark可以用于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)
4、兼容性:Spark可以非常方便地与其他的开源产品进行融合

启动流程:
1、启动master进程
2、Master开始解析conf目录的slaves配置文件,找到相应的Worker节点
3、开始启动Worker进程
4、worker向master发送注册信息(id,cpu,内存,核数等)
5、Master接受到Worker的注册信息后并保 存到内存和磁盘里,然后向Worker发送注册成功信息
6、worker周期性地向master发送心跳,Master更新worker的最后一次心跳时间
7、master删除超时的worker信息

任务提交流程完整流程:
1、Driver端首先启动SparkSubmit进程,启动后开始与Master进行通信,此时创建了一个非常重要的对象(SparkContext),接着向Master发送任务信息
2、Master接收到任务信息后,开始资源调度,此时会和所有的Worker进行通信。找到比较空闲的Worker,并通知Worker来取任务和启动相应的Excecutor
3、Executor启动后,开始与Driver进行反向注册,接下来Driver开始把任务发送给相应的Executor,Executor开始计算任务

RDD

RDD:resilient Distributed Dataset 弹性分布式数据集

RDD特点:自动容错,位置感知调度和可伸缩,并行处理

产生方式:
a、文件系统中加入
b、已有的scala集合
c、从RDD=>RDD
(RDD只支持粗粒度变换,即只记录单个块上执行的单个操作,然后创建某个RDD的变换序列存储下来,这个变换序列就是RDD的血统)

五大属性(也称数据结构):
是一个分区链表;有函数对其进行分区;
每个RDD都有依赖;
hash分区;
最优位置

内容 :
1、源数据切分后的数据块,源代码中的split变量
2、关于血统的信息,源码中的dependency变量
3、一个计算函数(一个rdd如何通过父rdd得到)
4、一些关于如何分块和数据存放的元信息

分区

为什么分区?
为了并行处理分析,分区多少决定并行计算的力度

分区数量根据集群worker的内核数2~4倍,分区计算逻辑:分区的大小、分区目标大小、分区最小值通过算法得出确定的分区大小

分区过多:task数量过多,资源调度过于频繁
分区过少:并行度不够 效率较低

hash分区:根据KV中K的hash值,用navigahash重新计算的分区,容易出现数据倾斜(有一个key数据巨大)
范围分区:划分范围分区

算子

action算子
聚合算子:有多个数据输入而只有一个输出的
collect
持久化

spark会用一个标志对rdd进行标记,一指示该rdd应当在spark作业运行时被缓存,spark可跨集群在内存中缓存数据集

什么情况下考虑缓存?
1、RDD进行shuffle
2、多个算子重复调用同一个RDD
3、运算逻辑比较复杂,某个RDD经常被调用
4、要求计算速度快
5、集群的资源足够大

缓存级别:

class StorageLevel private(
private var _useDisk: Boolean,    --是否使用磁盘
private var _useMemory: Boolean,    --是否使用内存
private var _useOffHeap: Boolean,    --是否:使用堆外内存,这是Java虚拟机里面的概念,堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内 存,这些内存直接受操作系统管理(而不是虚拟机)。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用 的影响。
private var _deserialized: Boolean,    --是否反序列化,其逆过程序列化(Serialization)是java提供的一种机制,将对象表示成一连串的字节; 而反序列化就表示将字节恢复为对象的过程。序列化是对象永久化的一种机制,可以将对象及其属性保存起来,并能在 反序列化后直接恢复这个对象 (false代表序列化)
private var _replication: Int = 1)    --副本数量(在多个节点上存放副本)

共享变量
通常情况下,一个传递给 Spark 操作(例如 map 或 reduce)的函数 func 是在远程的集群节点上执行的。该函数 func 在多个节点执行过程中使用的变量,是同一个变量的多个副本。这些变量的以副本的方式拷贝到每个机器上,并且各个远程机器上变量的更新并不会传播回 driver program(驱动程序)。通用且支持 read-write(读-写) 的共享变量在任务间是不能胜任的。所以,Spark 提供了两种特定类型的共享变量 : broadcast variables(广播变量)和 accumulators(累加器)。
广播变量
通过在一个变量 v 上调用 SparkContext.broadcast(v) 方法来进行创建。广播变量是 v 的一个 wrapper(包装器),可以通过调用 value方法来访问它的值。代码示例如下在创建广播变量之后,在集群上执行的所有的函数中,应该使用该广播变量代替原来的 v 值,所以节点上的 v 最多分发一次。另外,对象 v 在广播后不应该再被修改,以保证分发到所有的节点上的广播变量具有同样的值(例如,如果以后该变量会被运到一个新的节点)。
Accumulators(累加器)
是一个仅可以执行 “added”(添加)的变量来通过一个关联和交换操作,因此可以高效地执行支持并行。累加器可以用于实现 counter( 计数,类似在 MapReduce 中那样)或者 sums(求和)

两者都是需要多次调用的数据块,不同点是广播变量是val不可变的,而累加器是不断改变的

Spark RDD、DataFrame和DataSet的区别 ?
首先,Spark RDD、DataFrame和DataSet是Spark的三类API,DataFrame和DataSet是基于RDDs的,dataframe相比rdd处理结构化数据更方便,序列化也进行了优化,但是内存存储的是row对象而不能是自定义对象,dataset集合前两者的优点,并且得到了优化

一、RDD
RDD的优点:
1.相比于传统的MapReduce框架,Spark在RDD中内置很多函数操作,group,map,filter等,方便处理结构化或非结构化数据。
2.面向对象编程,直接存储的java对象,类型转化也安全
RDD的缺点:
1.由于它基本和hadoop一样万能的,因此没有针对特殊场景的优化,比如对于结构化数据处理相对于sql来比非常麻烦
2.默认采用的是java序列号方式,序列化结果比较大,而且数据存储在java堆内存中,导致gc比较频繁
二、DataFrame
DataFrame的优点:
1.结构化数据处理非常方便,支持Avro, CSV, elastic search, and Cassandra等kv数据,也支持HIVE tables, MySQL等传统数据表
2.有针对性的优化,如采用Kryo序列化,由于数据结构元信息spark已经保存,序列化时不需要带上元信息,大大的减少了序列化大小,而且数据保存在堆外内存中,减少了gc次数,所以运行更快。
3.hive兼容,支持hql、udf等
DataFrame的缺点:
1.编译时不能类型转化安全检查,运行时才能确定是否有问题
2.对于对象支持不友好,rdd内部数据直接以java对象存储,dataframe内存存储的是row对象而不能是自定义对象
三、DateSet
DateSet的优点:
1.DateSet整合了RDD和DataFrame的优点,支持结构化和非结构化数据
2.和RDD一样,支持自定义对象存储
3.和DataFrame一样,支持结构化数据的sql查询
4.采用堆外内存存储,gc友好
5.类型转化安全,代码友好

如何选择RDD还是DataFrame/DataSet?
前者提供低级别的功能和更多的控制,后者允许自定义视图和结构,提供高级和特定领域的操作,节省空间,并能够以极高的速度执行。

两种shuffle过程的比较
* MR shuffle:主要基于磁盘,计算速度慢,需要分区排序,浪费时间
* Spark shuffle:主要基于内存,计算速度快,可以迭代进行,效率高,计算时间短

算子分类:
Transformtion算子:Union map flatMap reduceByKey coalesce Repartition MapPartitions cogroup Distinct mapPartitionsWithIndex join parallelize cache persist? leftOuterJoin
Action算子:count take collect foreach saveAsTextFile frist reduce foreachPartition Checkpoint textFile
触发shuffle算子(产生Stage划分算子):distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition
触发Job算子:count take collect foreach saveAsTextFile frist reduce foreachPartition Checkpoint textFile

spark的优化:
使用高性能序列化类库
优化数据结构
对多次使用的RDD进行持久化/Checkpoint
使用序列化的持久化级别
java虚拟机垃圾回收调优
提高并行度
广播共享数据
数据本地化
Shuffle调优

Parquet格式是Spark SQL的默认数据源
Parquet是列式存储格式的一种文件类型.

**

RDD、DataFrame和DataSet的细致区别:

RDD
RDD是Spark建立之初的核心API。RDD是不可变分布式弹性数据集,在Spark集群中可跨节点分区,并提供分布式low-level API来操作RDD,包括transformation和action。何时使用RDD?使用RDD的一般场景: 你需要使用偏底层的transformation和action来控制你的数据集; 你的数据集非结构化,比如:流媒体或者文本流; 你想使用函数式编程来操作你的数据,而不是用特定领域语言(DSL)表达; 你不想加入schema,比如,当通过名字或者列处理(或访问)数据属性不在意列式存储格式; 当你可以放弃使用DataFrame和Dataset来优化结构化和半结构化数据集的时候。
DataFrames与RDD类似,DataFrame是不可变的分布式数据集合,与RDD不同的是,数据按列的方式组织,类似于关系型数据库的一张表。设计的初衷是使得大数据集的处理更简单, DataFrame允许用户在分布式数据集上施加一个结构,是对数据更高级的抽象,提供了具体的API处理分布式数据,同时使得Spark拥有更广泛的用户群。

DataFrame
与RDD相同之处,都是不可变分布式弹性数据集。不同之处在于,DataFrame的数据集都是按指定列存储,即结构化数据,类似于传统数据库中的表。DataFrame的设计是为了让大数据处理起来更容易。DataFrame允许开发者把结构化数据集导入DataFrame,并做了更高层次的抽象;DataFrame提供特定领域的语言(DSL)API来操作你的数据集。
在Spark2.0中,DataFrame API将会和Dataset API合并,统一数据处理API。由于这个统一“有点急”,导致大部分Spark开发者对Dataset的high-level和type-safe API并没有什么概念。

Dataset
是数据的分布式集合。数据集是Spark 1.6中添加的一个新接口,它提供RDDs的优点(强类型、使用强大lambda函数的能力)和Spark SQL的优点优化的执行引擎。可以从JVM对象构造数据集,然后使用它进行操作功能转换(映射、平面映射、过滤器等)。数据集API在Scala和Java中可用。Python不支持数据集API。但是由于Python的动态特性,许多数据集API的优点已经可用(即您可以自然地通过名称访问行字段)行。columnName)。R的情况类似//
从Spark2.0开始,DataSets扮演了两种不同的角色:强类型API和弱类型API,见下表。从概念上来讲,可以把DataFrame 当作一个泛型对象的集合DataSet[Row], Row是一个弱类型JVM 对象。相对应地,如果JVM对象是通过Scala的case class或者Java class来表示的,Dataset是强类型的

共性:
1、RDD、DataFrame、Dataset全都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
2、三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历运算
3、三者都会根据spark的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出
4、三者都有partition的概念

区别:
RDD和DataFrame:
1.对比于RDD,dataframe处理对象就是多了结构化,RDD可以加上序列化(Row是经过序列化了的)和结构信息描述(schema,就像表的字段描述信息)就是dataframe,所以dataframe可以注册成临时表,用sql处理数据。RDD是分布式的Java对象的集合。DataFrame是分布式的Row对象的集合。
2.DataFrame提升执行效率
RDD API是函数式的,强调不变性,在大部分场景下倾向于创建新对象而不是修改老对象。这一特点虽然带来了干净整洁的API,却也使得Spark应用程序在运行期倾向于创建大量临时对象,对GC造成压力。在现有RDD API的基础之上,我们固然可以利用mapPartitions方法来重载RDD单个分片内的数据创建方式,用复用可变对象的方式来减小对象分配和GC的开销,但这牺牲了代码的可读性,而且要求开发者对Spark运行时机制有一定的了解,门槛较高。另一方面,Spark SQL在框架内部已经在各种可能的情况下尽量重用对象,这样做虽然在内部会打破了不变性,但在将数据返回给用户时,还会重新转为不可变数据。利用 DataFrame API进行开发,可以免费地享受到这些优化效果。
3.DataFrame可以减少数据读取分析大数据,最快的方法就是 ——忽略它。这里的“忽略”并不是熟视无睹,而是根据查询条件进行恰当的剪枝。
4.执行优化
RDD和DataSet:
1.DataSet以Catalyst逻辑执行计划表示,并且数据以编码的二进制形式被存储,不需要反序列化就可以执行sorting、shuffle等操作。
2.DataSet创立需要一个显式的Encoder,把对象序列化为二进制,可以把对象的schema映射为Spark.SQl类型,然而RDD依赖于运行时反射机制。
DataFrame和DataSet
Dataset可以认为是DataFrame的一个特例,主要区别是Dataset每一个record存储的是一个强类型值而不是一个Row。
DataSet可以在编译时检查类型.并且是面向对象的编程接口。
后面版本DataFrame会继承DataSet,DataFrame是面向Spark SQL的接口。

猜你喜欢

转载自blog.csdn.net/ZJ_2459/article/details/88219365