3.Spark设计与运行原理,基本操作

1.Spark已打造出结构一体化、功能多样化的大数据生态系统,请用图文阐述Spark生态系统的组成及各组件的功能。

  目前,Spark生态系统已经发展成为一个可应用于大规模数据处理的统一分析引擎,它是基于内存计算的大数据并行计算框架,适用于各种各样的分布式平台的系统。在Spark生态圈中包含了Spark SQL、Spark Streaming、GraphX、MLlib等组件,这些组件可以非常容易地把各种处理流程整合在一起,而这样的整合,在实际的数据分析过程中是很有意义的。

  Spark Core:Spark核心组件,它实现了Spark的基本功能,包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core中还包含了对弹性分布式数据集(Resilient Distributed Datasets,简称RDD)的API 定义,RDD是只读的分区记录的集合,只能基于在稳定物理存储中的数据集和其他已有的RDD上执行确定性操作来创建。

  Spark SQL:用来操作结构化数据的核心组件,通过Spark SQL可以直接查询Hive、HBase等多种外部数据源中的数据。Spark SQL的重要特点是能够统一处理关系表和RDD。在处理结构化数据时,开发人员无需编写MapReduce程序,直接使用SQL命令就能完成更加复杂的数据查询操作。

  Spark Streaming:Spark提供的流式计算框架,支持高吞吐量、可容错处理的实时流式数据处理,其核心原理是将流数据分解成一系列短小的批处理作业,每个短小的批处理作业都可以使用Spark Core进行快速处理。Spark Streaming支持多种数据源,例如Kafka、Flume以及TCP套接字等数据源。

  MLlib:Spark提供的关于机器学习功能的算法程序库,包括分类、回归、聚类、协同过滤算法等,还提供了模型评估、数据导入等额外的功能,开发人员只需了解一定的机器学习算法知识就能进行机器学习方面的开发,降低了学习成本。

  GraphX:Spark提供的分布式图处理框架,拥有对图计算和图挖掘算法的API接口以及丰富的功能和运算符,极大的方便了对分布式图处理的需求,能在海量数据上运行复杂的图算法。

  独立调度器、Yarn、Mesos:Spark框架可以高效地在一个到数千个节点之间伸缩计算,集群管理器则主要负责各个节点的资源管理工作,为了实现这样的要求,同时获得最大灵活性,Spark支持在各种集群管理器(Cluster Manager)上运行,Hadoop Yarn、Apache Mesos以及Spark自带的独立调度器都被称为集群管理器。

  Spark计算框架在处理数据时,所有的中间数据都保存在内存中。正是由于Spark充分利用内存对数据进行计算,从而减少磁盘读写操作,增大了框架计算效率。同时Spark还兼容HDFS、Hive,可以很好地与Hadoop系统融合,从而弥补MapReduce高延迟的性能缺点。所以说,Spark是一个更加快速、高效的大数据计算平台。

2.请详细阐述Spark的几个主要概念及相互关系:

  Master, Worker;  RDD,DAG; Application, job,stage,task; driver,executor,Claster Manager;DAGScheduler, TaskScheduler.

(1). Master, Worker

Master-Worker模式是常用的并行设计模式。核心思想是,系统由两个角色组成,Master和Worker,Master负责接收和分配任务,Worker负责处理子任务。任务处理过程中,Master还负责监督任务进展和Worker的健康状态;Master将接收Client提交的任务,并将任务的进展汇总反馈给Client。各角色关系如下图 

 

 

 Master-Worker模式满足于可以将大任务划分为小任务的场景,是一种分而治之的设计理念。通过多线程或者多进程多机器的模式,可以将小任务处理分发给更多的CPU处理,降低单个CPU的计算量,通过并发/并行提高任务的完成速度,提高系统的性能。

(2). RDD,DAG

RDD叫作弹性分布式数据集,是spark中最基本也是最重要的概念之一。它是spark中一种基本的数据抽象,有容错机制并能够被并行操做的元素集合,具备只读、分区、容错、高效、无需物化、能够缓存、RDD依赖等特征。

  构建RDD形成DAG遇到Action的时候,前面的stage先提交,提交完成之后再交给下游的数据,在遇到TaskScheduler,这个时候当我们遇到Action的方法的时候,我们就会让Master决定让哪些Worker来执行这个调度,但是到了最后我们真正的传递的时候,我们用的是Driver给Worker传递数据(其实是传递到Excutor里面,这个里面执行真正的业务逻辑),Worker中的Excutor只要启动,则此后就和Master没有多大关系了。

  DAG(Directed Acyclic Graph)叫做有向无环图,原始的RDD通过一系列的转换就形成DAG,根据RDD的之间的依赖关系的不同将DAG划分为不同的stage,对于窄依赖,partition的转换处理在stage中完成计算,对于宽依赖,由于有shuffle的存在,只能在partentRDD处理完成后,才能开始接下来的计算,因此宽依赖是划分stage的依据一般我们认为join是宽依赖,但是对于已经分好区的join来说,我们此时可以认为这个时候的join是窄依赖。

(3).Application, job,stage,task

Application

application(应用)其实就是用spark-submit提交的程序。比方说spark examples中的计算pi的SparkPi。一个application通常包含三部分:从数据源(比方说HDFS)取数据形成RDD,通过RDD的transformation和action进行计算,将结果输出到console或者外部存储(比方说collect收集输出到console)。

Driver

 Spark中的driver感觉其实和yarn中Application Master的功能相类似。主要完成任务的调度以及和executor和cluster manager进行协调。有client和cluster联众模式。client模式driver在任务提交的机器上运行,而cluster模式会随机选择机器中的一台机器启动driver。从spark官网截图的一张图可以大致了解driver的功能。

Job

 Spark中的Job和MR中Job不一样不一样。MR中Job主要是Map或者Reduce Job。而Spark的Job其实很好区别,一个action算子就算一个Job,比方说count,first等。

Task

Task是Spark中最新的执行单元。RDD一般是带有partitions的,每个partition的在一个executor上的执行可以任务是一个Task。 

Stage

Stage概念是spark中独有的。一般而言一个Job会切换成一定数量的stage。各个stage之间按照顺序执行。至于stage是怎么切分的,首选得知道spark论文中提到的narrow dependency(窄依赖)和wide dependency( 宽依赖)的概念。其实很好区分,看一下父RDD中的数据是否进入不同的子RDD,如果只进入到一个子RDD则是窄依赖,否则就是宽依赖。宽依赖和窄依赖的边界就是stage的划分点。从spark的论文中的两张截图,可以清楚的理解宽窄依赖以及stage的划分。

(4).driver,executor,Claster Manager

driver就是我们编写的spark应用程序,用来创建sparkcontext或者sparksession,driver会和cluster mananer通信,并分配task到executor上执行。

Executors其实是一个独立的JVM进程,在每个工作节点上会起一个,主要用来执行task,一个executor内,可以同时并行的执行多个task。

Claster Manager负责整个程序的资源调度,目前的主要调度器有:YARN,Spark Standalone,Mesos。

(5).DAGScheduler, TaskScheduler.

spark 调度器分为两个部分, 一个是 DagScheduler, 一个是 TaskScheduler, DagScheduler 主要是用来把一个 Job 根据宽依赖划分为多个Stage(阶段),

对于划分出来的每个 stage 都抽象为一个  TaskSet任务集 交给  TaskScheduler 来进行进一步的调度运行。

 

3.在PySparkShell尝试以下代码,观察执行结果,理解sc,RDD,DAG。请画出相应的RDD转换关系图。 

 

 

 

 

 

 

pyspark
>>> sc
>>> lines = sc.textFile("file:///home/hadoop/sjh159.txt")
>>> lines
>>> words=lines.flatMap(lambda line:line.split())
>>> words
>>> wordKV=words.map(lambda word:(word,1))
>>> wordKV
>>> lineKV=lines.map(lambda line:(1,line))
>>> lineKV

>>> lines.foreach(print)
>>> words.foreach(print)
>>>wordKV.foreach(print)
>>>lineKV.foreach(print)

posted @ 2022-03-10 15:11  Sjh_code  阅读(83)  评论(0编辑  收藏  举报