继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

spark大数据架构初学入门基础详解

慕村9548890
关注TA
已关注
手记 1102
粉丝 227
获赞 987

Spark是什么

a) 是一种通用的大数据计算框架

b) Spark Core 离线计算

Spark SQL 交互式查询

Spark Streaming 实时流式计算

Spark MLlib 机器学习

Spark GraphX 图计算

c) 特点:

i. 一站式:一个技术堆栈解决大数据领域的计算问题

ii. 基于内存

d) Spark2009年诞生于伯克利大学的AMPLab实验室

2010年正式开源了Spark项目

2013年Spark成为Apache下的项目

2014年飞速发展,成为Apache的顶级项目

2015年在国内兴起,代替mr,hive,storm等

作者:辛湜(shi)

e) Spark和Hive:

Spark优点:

i. 速度快

ii. Spark SQL支持大量不同的数据源

f) Spark 和Storm

i. 计算模型不一样

ii. Spark吞吐量大

g) 特点:快,易用,通用,兼容性

h) spark运行模式

i. local(本地)

ii. standalone(集群)

iii. on yarn(由 yarn作为资源调度Spark负责任务调度和计算)

iv. on mesos(由mesos作为资源调度S)

v. on cloud()

i) 配置步骤

=======================on yarn====================

【说明】

1. spark任务运行在yarn上,由yarn来进行资源调度和管理,spark只负责任务的调度 和计算

2.不需要配置和启动spark集群

3.只需要在提交任务的节点上安装并配置spark on yarn 模式

4.必须找一台节点安装spark

5. 步骤:

i.安装配置JDK

ii. vi spark-env.sh

1. export  JAVA_HOME=/opt/modules/jdk1.7_6.0

2. export  HADOOP_CONF_DIR = /opt/modules/hadoop/etc/hadoop

iii.测试spark on yarn 模式是否安装成功

iv.网络测试:http://hadoop-yarn1.beicai.com:8088

=====================sdandalone模式==============

【说明】

1.  spark运行在spark 集群上,由spark进行资源调度管理,同时还负责任务的调度和 计算

2.需要配置和启动spark集群

3. 步骤:

i.安装配置JDK

ii.上传并解压Spark

iii.建立软连接 ln -s spark spark 或者修改名称

iv. 配置环境变量

v.安装配置Spark,修改spark配置文件(spark-env.sh, slaves)

1. vi spark-env.sh

a) export  JAVA_HOME=/opt/modules/jdk(jdk位置)

b) export SPARK_MASTER_IP=hadoop-yarn1.beicai.com

c) export SPARK_MASTER_PORT=7077

2.  vi slaves(用于指定在哪些节点上启动worker)

a) hadoop-yarn2.beicai.com

hadoop-yarn3.beicai.com

vi.将spark发送给其他主机

vii. 启动

/opt/modules/spark/bin/start-all.sh

vii. 查看SparkUI界面:http://hadoop-yarn1.beicai.com:8080

4. 

j) 

一、Spark原理

1、Spark的运行原理

i、分布式

Ii、主要基于内存(少数情况基于磁盘)

Iii、迭代式计算

2、Spark 计算模式 VS  MapReduce  计算模式对比

Mr这种计算模型比较固定,只有两种阶段,map阶段和reduce阶段,两个阶段结束 后,任务就结束了,这意味着我们的操作很有限,只能在map阶段和reduce阶段, 也同时意味着可能需要多个mr任务才能处理完这个job

Spark 是迭代式计算,一个阶段结束后,后面可以有多个阶段,直至任务计算完 成,也就意味着我们可以做很多的操作,这就是Spark计算模型比mr 强大的地方

三、什么是Spark RDD?

1、什么是RDD?

弹性的,分布式的,数据集

(RDD在逻辑上可以看出来是代表一个HDFS上的文件,他分为多个分区,散落 在Spark的多个节点上)

3、RDD----弹性

当RDD的某个分区的数据保存到某个节点上,当这个节点的内存有限,保存不了这个 分区的全部数据时,Spark就会有选择性的将部分数据保存到硬盘上,例如:当worker 的内存只能保存20w条数据时,但是RDD的这个分区有30w条数据,这时候Spark就 会将多余的10w条数据,保存到硬盘上去。Spark的这种有选择性的在内存和硬盘之间的权衡机制就是RDD的弹性特点所在

4、Spark的容错性

RDD最重要的特性就是,提供了容错性,可以自动的从失败的节点上恢复过来,即如 果某个节点上的RDD partition(数据),因为节点的故障丢了,那么RDD会自动的通过 自己的数据来源重新计算该partition,这一切对使用者来说是透明的

2、Spark的开发类型

(1)、核心开发:离线批处理 / 演示性的交互式数据处理

(2)、SQL查询:底层都是RDD和计算操作

(3)、底层都是RDD和计算操作

(4)、机器学习

(5)、图计算

3、Spark 核心开发(Spark-core == Spark-RDD)步骤

(1)、创建初始的RDD

(2)、对初始的RDD进行转换操作形成新的RDD,然后对新的RDD再进行操作,直 至操作计算完成

(3)、将最后的RDD的数据保存到某种介质中(hive、hdfs,MySQL、hbase...)

五、Spark原理

Driver,Master,Worker,Executor,Task各个节点之间的联系

Spark中的各节点的作用:

1、driver的作用:

(1)、 向master进行任务的注册

(2)、构建运行任务的基本环境

(3)、接受该任务的executor的反向注册

(4)、向属于该任务的executor分配任务

2、什么是driver?

我们编写的程序打成jar包后,然后找一台能够连接spark集群的节点做任务的driver,具体的表现为SparkSubmit

3、Master的作用:

(1)、监控集群;

(2)、动态感知worker的上下线;

(3)、接受driver端注册请求;

(4)、任务资源的调度

4、Worker的作用:

(1)、定时向master汇报状态;

(2)、接受master资源调度命令,进行资源的调度

(3)、启动任务的容器Executor

5、Executor的作用:

(1)、保存计算的RDD分区数据;

(2)、向Driver反向注册;

(3)、接受Driver端发送来的任务Task,作用在RDD上进行执行

Spark 编程的流程:

1、我们编写的程序打包成jar包,然后调用Spark-Submit 脚本做任务的提交

2、启动driver做任务的初始化

3、Driver会将任务极其参数(core,memory,driver相关的参数)进行封装成ApplicationDescript通过taskSchedulerImpl 提交给Master

4、Master接受到driver端注册任务请求时,会将请求参数进行解析,并封装成APP,然后进行持久化,并且加入到其任务队列中的waitingAPPs

5、当轮到咱们提交的任务运行时,master会调用schedule()这个方法,做任务资源调度

6、Master将调度好的资源封装成launchExecutor,发送给指定的worker

7、Worker接收到发送来的launchExecutor时,会将其解析并封装成ExecutorRunner,然后调用start方法,启动Executor

8、Executor启动后,会向任务的Driver进行反向注册

9、当属于这个任务的所有executor启动成功并反向注册完之后,driver会结束SparkContext对象的初始化

10、当sc 初始化成功后,意味着运行任务的基本环境已经准备好了,driver会继续运行我们编写好的代码

11、开始注册初始的RDD,并且不断的进行转换操作,当触发了一个action算子时,意味着触发了一个job,此时driver就会将RDD之间的依赖关系划分成一个一个的stage,并将stage封装成taskset,然后将taskset中的每个task进行序列化,封装成launchtask,发送给指定的executor执行

12、Executor接受到driver发送过来的任务task,会对task进行反序列化,然后将对应的算子(flatmap,map,reduceByKey。。。。)作用在RDD分区上

六、RDD详解

1、什么是RDD?

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

2、RDD的特点:

自动容错

位置感知性调度

伸缩性

3、RDD的属性:

(1)、一组分片(partition),即数据集的基本组成单位。对于RDD来说,每个分片都会被一个计算任务处理,并决定并行计算的粒度,用户可以在创建RDD时指定RDD的分片个数,如果没有指定,那么就会采用默认值,默认值就是程序所分配到的CPU Core的数目

(2)、一个计算每个分区的函数。Spark中RDD的计算是以分片为单位的,每个RDD都会实现computer函数以达到这个目的。Computer函数会对迭代器进行复合,不需要保存每次计算的结果。

(3)、RDD之间的依赖关系。RDD的每次转换都会生成一个新的RDD,所以RDD之间就会形成类似于流水一样的前后依赖关系。在部分分区数据丢失时,Spark可以通过这个依赖关系重新计算丢失的分区数据,而不是对RDD的所有分区进行重新计算。

(4)、一个partition,即RDD的分片函数。当前Spark中实现了两种类型的分片函数,一个是基于hashPartitioner,另外一个是基于范围的RangePartitioner。只有对于key-value的RDD,才会有Partitioner,非key-value的RDD的Partitioner的值是None。Partitioner函数不但决定了RDD本身的分片数量,也决定了partition RDD Shuffle输出时的分片数量。

(5)、一个列表,存储存取每个Partition的优先位置(preferred location)。对于一个HDFD文件来说。这个列表保存的就是每个Partition所在的快的位置。按照“移动数据不如移动计算”的理念。Spark在进行任务调度的时候,会尽可能的将计算任务分配到所要处理数据块的存储位置。

4、RDD的创建:

进行Spark核心编程时,首先要做的事就是创建一个初始的RDD。Spark Core提供了三种创建RDD的方式:

(1)、使用程序中的集合创建RDD (调用parallelize()方法)

(2)、使用本地文件创建RDD(调用textFile()方法)

(3)、使用HDFD文件创建RDD  (调用textFile()方法)

七、算子

1、什么是算子?

是RDD中定义的作用在每一个RDD分片上的函数,可以对RDD中的数据进行转换 和操作

2、RDD算子的分类

(1)、Transformation算子,这类算子变换不触发提交作业(特点就是lazy特性)

返回的是一个RDD

(2)、Action算子,这类算子会触发SparkContext提交作业(触发一个spark job的运行,从而触发这个action之前所有的transformation的执行)

返回的是一个spark对象

3、常用的Transformation算子

八、RDD分区排序

I、分区

两种实现方式:coalesce和 repartition(底层调用coalesce)

coalesce(numPartitons,isShuffle)

第一个参数是重分区后的数量,第二个参数是是否进行shuffle

如果原来有N个分区,重分区后有M个分区

如果 M > N ,必须将第二参数设置为true(也就是进行shuffle),等价于 repartition(numPartitons)    如果是false将不起作用  

如果M < N

100-->10 重分区后的分区数比原来的小的多,那么久需要使用shuffle,也即是设置为true

100-->90 重分区后的分区数和原来的差不多的,那么就不需要使用shuffle,也就是设置为false

II、排序

sortBy(x => x)这个算子中带有隐式转换参数

x 能够排序(比较大小),那么这个类就必须有比较大小的功能,也就是实现了compareTo 或者compare

实现二次排序有两种方法:

1、继承Comparable 接口 或者 Ordered

2、隐式转换:可以定义隐式转换函数(Ordered)或者隐式转换值(Ordering)

九、自定义分区

自定义分区

要求:按照key将对应的value输出到指定的分区中

解释:自定义一个自定义分区类,继承partitioner,实现他的两个方法

1、numPartitions

2、getPartition

具体的功能根据项目的要求自定义实现,然后调用partitionBy方法,new出自定义的类,传入参数即可

九、RDD持久化原理

1、持久化场景:对于一个rdd会被多次引用到,并且这个rdd计算过程复杂,计算时间特变耗时

2、如何进行持久化,调用rdd.persist方法或cache方法,cache方法底层就是调用persist方法

******************persist(StorageLevel.MEMORY_ONLY)*******************

如果对RDD做持久化,默认持久化级别是storageLevel.MEMORY_ONLY ,也就是持久化到内存中去,这种持久化级别是效率最快的,但是由于是纯Java 对象,保存到内存中,那么内存可能保存的数量就会较少

***************persist(StorageLevel.MEMORY_ONLY_SER)****************

如果当我们集群资源有限时,那么我们可以采用MEMORY_ONLY_SER,也就是将Java对象进行序列化之后持久到内存中去,这种持久化的好处是能够持久化更多的数据到内存中,但是由于在持久化时需要序列化,取出来之后又需要反序列化这一过程,这个过程会消耗CPU计算资源,性能相对于MEMORY_ONLY 这种持久化级别来说稍微弱点,但是还是比较高效的

3、如何选择RDD持久化策略?

Spark提供的多种持久化级别,主要是为了在CPU和内存消耗之间进行取舍,下面是一些通用的持久化级别的选择建议:

1)、优先使用MEMORY_ONLY,如果可以缓存所有数据的话,那么就使用这种策略,因为纯内存速度最快,而且没有序列化,不需要消耗CPU进行反序列化操作

2)、如果MEMORY_ONLY策略,无法存储所有数据的话,那么使用MEMORY_ONLY_SER,将数据进行序列化存储,纯内存操作还是非常快的,只是要消耗CPU进行反序列化

3)、如果需要进行快速的失败恢复,那么就选择带后缀为_2的策略,进行数据的备份,这样在失败时,就不需要重新计算了

4、能不使用DISK相关的策略,就不要使用,有的时候,从磁盘读取数据,还不如重新计算一次

十一、共享变量

1、共享变量分为两种:广播变量 和 累加器

广播变量(broadcast)

2、日常所遇问题

因为每个task都需要拷贝这样的一个副本到executor去执行,那么我们可以想象一下,如果有1000 个task在某个worker上执行,而这个副本有100M,那么意味着我们需要拷贝100G的数据都到某个worker上执行,这样的话会大大消耗我们的网络流量,同时会加大executor的内存消耗,从而增加了我们spark作业的运行时间,大大降低了spark作业的运行效率,增加了作业失败的概率

3、如何解决以上问题,也就是说什么时候使用广播变量?

当RDD引用到了一个外部变量并且这个外部变量数据量不小,同时这个RDD对应的task数量特别多,那么此时使用广播共享变量再合适不过了

我们可以将这种大的外部变量做成广播变量,外部变量做成广播变量的时候,那么每个executor的内存中只会有一个外部变量,而这个副本针对所有的task都是共享的,这样的话就减少了网络流量消耗,降低了executor的内存消耗,提高了spark作业运行效率和缩短了运行时间,同时降低了作业失败的概率

4、广播变量的使用流程:

1)、某个executor的第一个task先执行,首先会从自己的blockManager中查找外部变量,如果没有就从邻居的executor的blockManager的内存中获取这个外部变量,如果还是获取不到,就从driver端获取,拷贝这个外部变量到本地的executor的blockManager

2)、当这个executor的其他task执行时,就不需要从外面获取这个外部变量的副本,直接从本地的blockManager中获取即可

5、如何获取广播变量的值?

可以直接调用广播变量的value() 这个方法即可

【注意】广播变量是只读的,不可写

累加器(Accumulator)

Spark提供的Accumulator ,主要用于多个节点对一个变量进行共享性的操作,Accumulator只是提供了累加的功能。但是却给我们提供了多个task对一个变量并行操作的功能,但是task只能对Accumulator进行累加操作

【注意】task只能对Accumulator进行类加操作,只有Driver程序可以读取Accumulator的值

RDD分区和容错机制讲解

1、RDD 的Lineage血统

RDD只支持粗粒度转换,即在大量记录上执行的单个操作,将创建RDD的一系列Lineage(血统)记录下来。以便恢复丢失的分区

2、RDD的依赖关系

RDD和它的父RDD的关系有两种不同的类型:

1)、窄依赖(一对一,多对一)

形象的比喻:独生子女

2)、宽依赖(多对多)

形象的比喻:超生

注释:划分stage的依据就是宽依赖,也就是RDD之间是否有shuffle,shuffle过程就是一个宽依赖过程,shuffle之前的tasks就属于一个stage,shuffle之后的也属于一个stage,shuffle之前和之后的操作都是窄依赖

【注意】shuffle过程分为:shuffle Write过程 和 shuffle read过程

4、DAG的生成(有向无环图)和任务的划分

DAG(Directed Acyclic Graph)叫做有向无环图(有方向无循环的图)

5、一个wordCount过程会产生多少个RDD?

至少会产生五个RDD,

第一个,从HDFS中加载后得到一个RDD(即使用sc.textFile()算子),即HadoopRDD

在sc.textFile()过程中还会产生一个RDD(调用map算子),产生一个MapPartitionRDD

第二个,使用flatMap算子,得到一个MapPartitionRDD

第三个,使用map算子,得到一个MapPartitionRDD

第四个,使用reduceByKey算子,也就是在经过了shuffle过程后又会得到一个shuffledRDD

第五个,使用saveAsTextFile算子,再产生一个MapPartitionRDD 

spark程序提交流程讲解

Spark任务简介:

Spark-submit--->SparkSubmit-->main-->submit-->doRunMain-->RunMain-->通过反射创建我们编写的主类的实例对象,调用main方法-->开始执行我们编写的代码-->初始化SparkContext对象-->创建初始的RDD-->触发action算子-->提交job-->worker执行任务-->任务结束

Spark任务详解:

1)、将我们编写的程序打成jar包

2)、调用spark-submit脚本提交任务到集群上运行

3)、运行sparkSubmit的main方法,在这个方法中通过反射的方式创建我们编写的主类的实例对象,然后调用main方法,开始执行我们的代码(注意,我们的spark程序中的driver就运行在sparkSubmit进程中)

4)、当代码运行到创建SparkContext对象时,那就开始初始化SparkContext对象了

5)、在初始化SparkContext对象的时候,会创建两个特别重要的对象,分别是:DAGScheduler

和TaskScheduler

【DAGScheduler的作用】将RDD的依赖切分成一个一个的stage,然后将stage作为taskSet提交给DriverActor

6)、在构建taskScheduler的同时,会创建两个非常重要的对象,分别是DriverActor和ClientActor

【clientActor的作用】向master注册用户提交的任务

【DriverActor的作用】接受executor的反向注册,将任务提交给executor

7)、当clientActor启动后,会将用户提交的任务和相关的参数封装到ApplicationDescription对象中,然后提交给master进行任务的注册

8)、当master接受到clientActor提交的任务请求时,会将请求参数进行解析,并封装成Application,然后将其持久化,然后将其加入到任务队列waitingApps中

9)、当轮到我们提交的任务运行时,就开始调用schedule(),进行任务资源的调度

10)、master将调度好的资源封装到launchExecutor中发送给指定的worker

11)、worker接受到Maseter发送来的launchExecutor时,会将其解压并封装到ExecutorRunner中,然后调用这个对象的start(), 启动Executor

12)、Executor启动后会向DriverActor进行反向注册

13)、driverActor会发送注册成功的消息给Executor

14)、Executor接受到DriverActor注册成功的消息后会创建一个线程池,用于执行DriverActor发送过来的task任务

15)、当属于这个任务的所有的Executor启动并反向注册成功后,就意味着运行这个任务的环境已经准备好了,driver会结束SparkContext对象的初始化,也就意味着new SparkContext这句代码运行完成

16)、当初始化sc成功后,driver端就会继续运行我们编写的代码,然后开始创建初始的RDD,然后进行一系列转换操作,当遇到一个action算子时,也就意味着触发了一个job

17)、driver会将这个job提交给DAGScheduler

18)、DAGScheduler将接受到的job,从最后一个算子向前推导,将DAG依据宽依赖划分成一个一个的stage,然后将stage封装成taskSet,并将taskSet中的task提交给DriverActor

19)、DriverActor接受到DAGScheduler发送过来的task,会拿到一个序列化器,对task进行序列化,然后将序列化好的task封装到launchTask中,然后将launchTask发送给指定的Executor

20)、Executor接受到了DriverActor发送过来的launchTask时,会拿到一个反序列化器,对launchTask进行反序列化,封装到TaskRunner中,然后从Executor这个线程池中获取一个线程,将反序列化好的任务中的算子作用在RDD对应的分区上

【注意】

Spark的任务分为为两种:

a、shuffleMapTask:shuffle之前的任务

b、resultTask:shuffle之后的任务

Spark任务的本质:

将RDD的依赖关系切分成一个一个的stage,然后将stage作为TaskSet分批次的发送到Executor上执行

十三、Checkpoint

1、使用checkpoint的场景:

某个RDD会被多次引用,计算特别复杂,计算特别耗时

担心中间某些关键的,在后面会反复几次使用的RDD,可能会因为节点的故障,导致持久化数据的丢失

2、如何对RDD进行checkpoint?

1)、设置还原点目录,设置checkpoint目录

2)、调用RDD的checkpoint的方法对该RDD进行checkpoint

3、checkpoint的原理

1)、RDD调用了checkpoint方法之后,就接受RDDCheckpointData对象的管理

2)、RDDCheckpointData对象会负责将调用了checkpoint的RDD 的状态设置为MarkedForCheckpoint

3)、当这个RDD所在的job运行结束后,会调用最后一个RDD的doCheckpoint,根据其血统向上查找,查找到被标注为MarkedForCheckpoint状态的RDD,将其状态改变为checkpointingInProgress

4)、启动一个单独的job,将血统中标记为checkpointingInProgress的RDD进行checkpoint,也就是将RDD的数据写入到checkpoint的目录中去

5)、当某个节点发生故障,导致包括持久化的数据全部丢失,此时会从还原点目录还原RDD的每个分区的数据,这样就不需要从头开始计算一次

4、checkpoint需要注意的地方

因为RDD在做checkpoint的时候,会单独启动一个job对需要进行checkpoint的RDD进行重新计算,这样就会增加spark作业运行时间,所以spark强烈建议在做checkpoint之前,应该对需要进行checkpoint的RDD进行持久化(即调用 .cache)

5、checkpoint 和持久化的区别

1)、是否改变血统:

持久化(.cache):不会改变RDD的依赖关系,也就是不会改变其血统

Checkpoint:会改变RDD的血统,做了checkpoint的RDD会清除其所有的依赖关系,并将其父RDD强制设置为checkpointRDD,并且将RDD的状态更改为checkpointed

2)、RDD的数据的可靠性:

持久化:只是将RDD的数据持久化到内存或磁盘中,但是如果节点发生故障,那么持久化的数据还是会丢失

Checkpoint:checkpoint的数据保存在第三方高可靠的分布式的文件系统中,机试节点发生故障,数据也不会丢失,所以checkpoint比持久化可靠性更高

6、后续

我们实现了checkpoint 之后,在某个task 又调用了该RDD的iterator() 方法时,就实现了高容错机制,即使RDD的持久化数据丢失,或者压根儿就没有持久化,但是还是可以通过readCheckpointOrComputer() 方法,优先从父RDD-----checkpointRDD中读取,HDFS(外部文件系统)的数据

第二部分 spark-sql

一、Spark-SQL前世今生

1、Spark SQL的特点

1)、支持多种数据源:Hive、RDD、Parquet、JSON、JDBC等。

2)、多种性能优化技术:in-memory columnar storage、byte-code generation、cost model动态评估等。

3)、组件扩展性:对于SQL的语法解析器、分析器以及优化器,用户都可以自己重新开发,并且动态扩展

2、Spark SQL的性能优化技术简介

1)、内存列存储(in-memory columnar storage)

2)、字节码生成技术(byte-code generation)

3)、Scala代码编写的优化

3、Spark SQL and DataFrame

Spark SQL是Spark中的一个模块,主要用于进行结构化数据的处理。它提供的最核心的编程抽象,就是DataFrame。同时Spark SQL还可以作为分布式的SQL查询引擎。Spark SQL最重要的功能之一,就是从Hive中查询数据。

DataFrame,可以理解为是,以列的形式组织的,分布式的数据集合。它其实和关系型数据库中的表非常类似,但是底层做了很多的优化。DataFrame可以通过很多来源进行构建,包括:结构化的数据文件,Hive中的表,外部的关系型数据库,以及RDD。

二、Spark-sql的使用

1、RDD转换为DataFrame(两种)

1)、使用反射的方式来推断包含了特定数据类型的RDD的元数据

2)、通过编程接口来创建DataFrame

2、UDF自定义函数和UDAF自定义聚合函数

UDF,其实更多的是针对单行输入,返回一个输出

UDAF,则可以针对多行输入,进行聚合计算,返回一个输出,功能更加强大

3、Spark-SQL工作原理

SqlParse  --------->解析器

Analyser  --------->分析器

Optimizer  --------->优化器

SparkPlan  --------->物理计划

流程:

1)、自己编写的SQL语句

大家要知道,只要在数据库类型的技术里面,比如:最传统的MySQL,Oracle等,包括现在大数据领域的数据仓库,比如hive,他的基本的SQL执行的模型,都是类似的,首先都要生成一条SQL语句的执行计划

2)、通过SqlParser(解析器)生成未解析的逻辑计划(unresolved LogicalPlan)

3)、通过Analyzer(分析器)生成解析后的逻辑计划(resolved LogicalPlan)

4)、通过Optimizer(优化器)生成优化后的逻辑计划(optimized LogicalPlan)

实际上,比如传统的Oracle等数据库,通常都会生成多个执行计划,然后呢,最后有一个优化器,针对多个计划,选择一个最好的计划,而SparkSql这儿的优化指的是,比如说,刚生成的执行计划中,有些地方的性能是显而易见的,不太好,举例说明:

比如说,我们有一个SQL语句,select name from (select ... from ...) where ..=..;

此时,在执行计划解析出来的时候,其实就是按照他原封不动的样子,来解析成可以执行的计划,但是呢,Optimizer 在这里其实就会对执行计划进行优化,比如说,发现where 条件,其实可以放在子查询中,这样,子查询的数量大大变小,可以优化执行速度,此时,可能就会变成如下这样:select name from (select name from ...where ..=..)

5)、通过SparkPlan,生成最后的物理计划(PhysicalPlan)

到物理计划这里,那么其实就是非常“接地气”的计划了。就是说,已经很明朗了,从那几个文件读取什么数据,从那几个文件中读取,如何进行关联等等

6)、在executor中执行物理计划

逻辑的执行计划,更多的是偏向于逻辑,比如说吧,大致就是这种样子的,

From table students=>filter ... => select name ...

这里基本上,逻辑计划都是采用Tree ,树形结构

7)、生成RDD

Select  name  from  students => 解析,从哪里去查询,students表,在哪个文件里,从哪个文件中查询哪些数据,比如说是name这个列,此外,复杂的SQL,还有,比如说查询时,是否对表中的数据进行过滤和筛选,更不用说,复杂时,需要有多表的JOIN(咋传统数据库中,比如MySQL,执行计划还涉及到如何扫描和利用索引)

4、spark-SQL性能优化

1)、设置shuffle过程的并行度:spark.sql.shuffle.partitions(SQLContext.setConf())

2)、在hive数据仓库建设过程中,合理设置数据类型,比如能设置为int的,就不要设置为bigInt,减少数据类型导致不必要的内存开销

3)、编写SQL时,尽量给出明确的列名,比如select name from students。不要写select * 的方式。

4)、并行处理查询结果:对于spark-SQL查询的结果,如果数据量比较大,比如超过1000条,那么就不要一次性的collect()到driver再处理,使用foreach()算子,并行处理查询结果

5)、缓存表:对于一条SQL语句可能对此使用到的表,可以对其进行缓存,使用 sqlContext.cacheTable(tableName),或者DataFrame.cache()即可,spark-SQL会用内存列存储的格式进行表的缓存,然后spark-sql就可以仅仅扫描需要使用的列,并且自动优化压缩,来最小化内存使用和GC开销,SQLContext.uncacheTable(tableName)可以将表从缓存中移除,用SQLContext。setConf(),设置spark.sql.inMemoryColumnarStorage.batchSize参数(默认10000),可以设置列存储的单位

6)、广播join表:spark.sql.autoBroadcastJoinThreshold,默认10485760 (10 MB)。在内存够用的情况下,可以增加其大小,参数设置了一个表在join的时候,最大在多大以内,可以被广播出去优化性能

5、Hive on Spark配置

1)、安转配置好Hive和Spark

2)、Set hive.execution.engine=spark;

3)、set spark.master=spark://mini1:7077

第三部分spark-streaming

1,  Dstream

 

Dstream是sparkStreaming的数据模型,本质就是一连串不间断的RDD,但是它是一个时间段的RDD.这些时间段的RDD源源不断的连接在一起。

这个时间可以自己设置,时间设置的越短,实时性越高,但是性能消耗也越大。

2,  spark streaming从kafka获取数据,有哪几种方式?

 

有两种方式:

1.通过receiver的方式,

2,通过direct的方式,dirrect的方式需要自己来管理偏移量。

 

3,  sparkStreaming和storm的区别

sparkStreaming是spark里面的一个做流式准实时计算的组件,它使用的数据结构是Dstream,Dstream里面是一连串时间片的rdd。

相比于storm,sparkStreaming在实时性,保证数据不丢失方面都不占用优势,spark streaming在spark支持者眼中的优势是spark Streaming具有高吞吐性,最本质来说,sparkStreaming相比于storm的优势是sparkStreaming可以和spark core,spark SQL无缝整合。

4.对于需要多次引用的,并且这个dstream计算时间特别耗时,数据特别重要,那么我们就需要对dstream进行checkpoint,(只有多次引用的,进行持久化就可以了),因为即使对这个dstream进行持久化,数据也可能会丢失,而checkpoint数据丢失的可能性小,但是这样会影响spark-streaming的数据吞吐量,因为在做计算的同时,还需要将数据写入到外部存储系统中,会降低spark性能,影响吞吐量,非必要情况下不建议使用

5.如何对dstream做checkpoint

 

首先设置还原点目录,其次调用dstream的checkpoint方法

【注意】:dstream的checkpoint的周期一定要是产生batch时间的整数倍,同时spark官方建议将checkpoint的时间设置为至少10秒。通常来说,将checkpoint间隔设置为窗口操作的滑动间隔的5-10倍

6.spark程序在启动时,会去这个checkpointPath目录下查看是否有保存的driver的元数据(1.dstream的操作转换关系,2.未处理完的batch)信息,当spark-streaming程序在二次启动后就会去checkpointPath目录下还原这个程序,加载未处理的batch元数据信息在内存中恢复,继续进行任务处理

7.为了保证spark-streaming程序7*24小时运行,那么我们程序应该具备高可靠性,怎样具备高可靠性?

 

a.程序出现故障,driver死掉了,流式程序应该具备自动重启的功能

b.没有计算完成的rdd在程序异常停止后,下次启动后还会将未处理的rdd进行处理

【注意】:要在spark_submit中,添加--deploy-mode参数,默认其值为client,即在提交应用的机器上启动driver,但是要能够自动重启driver,就必须将其值设置为cluster;此外,需要添加--supervise参数,失败后自动重启

//spark_submit --executor-memory 1g --total-execute-cores 5 --deploy-model cluster --supervise

8.启用预写机制

a.预写日志机制,简写为WAL,全称为Write Ahead Log,从spark1.2版本开始,就引入了基于容错的文件系统的WAL机制。如果启用该机制,Receiver接收到的所有数据都会写入配置的checkpoint目录中的预写日志。这中机制可以让driver在恢复的时候,避免数据丢失,并且可以确保整个实时计算过程中零数据丢失

b.要配置该机制,首先调用StreamingContext的checkpoint()方法设置一个checkpoint目录,然后需要将spark.streaming.receiver.writeAheadLog.enable参数设置为true

然而,这种极强的可靠性机制,会导致Receiver的吞吐量大幅度下降,因为单位时间内,有相当一部分时间需要将数据写入预写日志。如果又希望开启预写日志机制,确保数据零损失,又不希望影响系统的吞吐量,那么可以创建多个输入DStream,启动多个Receiver

此外,在启用了预写日志机制之后,推荐将复制持久化机制禁用掉,因为所有数据已经保存在容错的文件系统中,不需要在用复制机制进行持久化,保存一份副本,只要将输入的DStream的持久化机制设置一下即可,persist(StorageLevel.MEMORY_AND_DISK_SER)。

9.spark-Streaming checkpoint概述

每一个spark-streaming应用,正常来说,都是7*24小时运转的,这就是实时计算程序的特点,因为要持续不断的对数据进行计算,因此,对实时计算应用的要求,应该是必须要能够对与应用程序逻辑无关的失败,进行容错

如果要实现这个目标,Spark Streaming程序就必须将足够的信息checkpoint到容错的存储系统上,从而让它能够从失败中进行恢复

有两种数据需要被进行checkpoint

1.元数据checkpoint-将定义了流式计算逻辑的信息,保存到容错的存储系统上,比如HDFS,当运行spark Streaming应用程序的Driver进程所在的节点失败时,该信息可以用于进行恢复,元数据信息包括:

a.配置信息---创建spark Streaming应用程序的配置信息,比如sparkConf中的信息

b.DStream的操作信息---定义了spark Stream应用程序的计算逻辑的DStream操作信息

c.未处理的batch信息---那些job正在排队,还没处理的batch信息

2.数据checkpoint---将实时计算过程中产生的RDD的数据保存到可靠的存储系统中。对于一些将多个batch的数据进行聚合,有状态的transformation操作,这是非常有用的,在这种transformation操作中,生成的RDD是依赖于之前batch的RDD的,这会导致随着时间的推移,RDD的依赖链条变得越来越长,要避免由于依赖链条越来越长,导致的一起变得越来越长的失败恢复时间,有状态的transformation操作执行过程中中间产生的RDD,会定期被checkpoint到可靠的存储系统上,比如HDFS,从而削减RDD的依赖链条进而缩短失败恢复时,RDD的恢复时间。一句话概括,元数据checkpoint主要是为了从driver失败中进行恢复;而RDD checkpoint主要是为了使用到有状态的transformation操作时,能够在其生产出的数据丢失时,进行快速的失败恢复

10.何时启用checkpoint机制?

a.使用了有状态的transformation操作----比如updateStateByKey,或者reduceByKeyAndWindow操作被使用了,那么checkpoint目录要求必须提供的,也就是必须开启checkpoint机制,从而进行周期性的RDD checkpoint

b.要保证可以从Driver失败中进行恢复-----元数据checkpoint需要启用,来进行这种情况的恢复

【注意】并不是说,所有的spark streaming应用程序,都要启用checkpoint机制,如果既不强制要求从Driver失败中自动进行恢复,又没使用有状态的transformation操作,那么就不需要启用checkpoint,事实上,这么做反而是有助于提升性能的

11.如何自动从Driver失败中恢复过来

 

要能够自动从Driver失败中恢复过来运行spark Streaming应用程序的集群,就必须监控Driver运行的过程,并且在他失败时将他重启,对于spark自身的standalone模式,需要进行一些配置去supervise driver,在他失败时将其重启

首先,要在spark-submit中,添加--deploy-mode参数,默认其值为client,即在提交应用的机器上启动Driver,但是,要能够自动重启Driver,就必须将其值设置为cluster,此外,需要添加--supervise参数。



作者:Alukar
链接:https://www.jianshu.com/p/f1245a1a3343


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP