简介

(1)Apache Spark是一个开源分布式计算框架,它提供并行处理通用数据的方法,用于对不同大小和结构的数据进行不同的数据处理任务。
(2)Spark本身并不用于数据存储,它在 JVMs上执行,并只会持续一个Spark应用程序运行时的时间。
(3)Spark支持在一台机器上本地运行(称为本地模式)。
(4)Spark可以与分布式存储系统(例如,HDFS、Cassandra或S3)一起使用。
(5)集群管理器协调整个集群的Spark应用程序的分布。Spark目前支持三种集群管理器:StandaloneApache MesosHadoop YARN
在这里插入图片描述

Spark组件

(1)Spark Core。Spark生态中的主要数据处理框架。Spark是围绕一个称为分布式弹性数据集(RDDs,Resilient Distributed Datasets)的数据抽象所构建。RDD具有“延迟执行”,“静态”,“分布式”等特征,并包含大量Transformation用于操作分布式数据集,例如map,join,reduce以及一些I/O操作读取写入数据操作。
(2)SparkSQL。SparkSQL是Spark性能的一个非常重要的组件,整合了 SQL 查询和 Spark 编程。
(3)Spark ML和Spark MLlib。两个都是Spark的机器学习库。
(4)Spark Streaming使用基于Spark Core对小批量数据进行流媒体分析。

分布式弹性数据集(RDDs,Resilient Distributed Datasets)

RDDs的主要特征:
(1)不可变的(immutable)。RDDs的这个特性就像Java变量加了final关键字一样。所以当用transformation对RDDs进行操作时,都是会新声明一个变量来“接收”。
(2)分布式的(distributed)。组成rdd的对象被称为分区(partitions),可以在指定系统的不同节点上进行计算。
(3)延迟执行(lazy evaluation)。

延迟执行(Lazy Evaluation)

Spark程序在执行时,除非遇到Action,否则程序不会真正针对partitions里的数据进行处理。Spark先根据程序评估一系列的步骤(这一系列的步骤可以成为执行计划), 然后才开始处理数据。

注意:并不是所有的transformation都是延迟执行的。例如:sortByKey,这个方法需要先评估RDD中数据的范围,所以它既是Transformation,也是Action。

延迟执行的好处

延迟执行可以避免数据进行多次传递,例如,假设要在同一个RDD上调用一个map和filter,那么Spark可以将它们发送给每一个executor,此时Spark就可以在每一个partition里执行map和filter,这只需要访问这些记录一次,而不是发送两组指令和访问每个partition两次。此外相比Hadoop的mapreduce,Spark的延迟执行范式更有利于实现。

def simpleWordCount(rdd: RDD[String]): RDD[(String, Int)] = {
 val words = rdd.flatMap(_.split(" "))
 val wordPairs = words.map((_, 1))
 val wordCounts = wordPairs.reduceByKey(_ + _)
 wordCounts
 }

内存数据的持久化和内存管理

Spark针对算法流程过程中数据的存储,提供了三种方式。非序列化的Java对象序列化数据硬盘Java对象结构清晰,使用起来比较方便,但是它对内存的利用相对比较低效;将数据序列化需要消耗一些时间,但是序列化之后的数据有利于保存在硬盘上,通常是存在文件中,并且序列化更有利于实现远程通信,在网络上传送对象的字节序列,将对象从一个地方传递到另一个地方;当内存不够用时,Spark就会将超出的部分存在硬盘中。

RDD的不可变性

RDD是静态并且不可变的,在一个RDD上的调用和转换会产生一个新的RDD,而不会改变原有RDD。创建RDDs的三种方式:
(1)通过一个现有的RDD 转换(transform)出一个新的RDD。
(2)通过SparkContext创建。
(3)通过DataFrame和DataSet(这些可以用SparkSession)。

RDDs的五大属性:
(1)partitions():返回RDD中的分区对象的数组。每个分区的索引值可以通过处于分区内的数据调用getPartition来获取;
(2)iterator(p,parentIters):基于给定的父RDD,查找对应子分区所有对象;
(3)dependencies():返回依赖对象的序列,这个方法可以让我们知道RDD之间的依赖关系。
(4)partitoner():返回RDD里分区的类型,scala的option类型。
(5)preferredLocations§:找到数据分区的所在节点地址。

宽/窄依赖

窄依赖是指,子RDD的每个分区对父RDD的分区都有简单,有限的依赖关系。换言之,每个父分区最多有一个子分区依赖,并且父分区的数据在被转换到子分区时,只需要针对自己分区内的数据进行转换。不需要预先考虑别的分区。

窄依赖
在这里插入图片描述
宽依赖
在这里插入图片描述

Spark程序运行过程的剖析

在Spark延迟执行的模式下,Spark的应用程序不会执行,直到Spark的驱动程序调用一个Action。对于每一次调用Action,Spark 的Scheduler(调度器)会创建一个可执行图,并创建一个Spark Job。每一个Job由很多个Stage组成。这些Stages是到达最终RDD所需要的步骤。
在这里插入图片描述
上图展示了Spark各个组件与API的对应关系。从上图可以看出,一个Spark应用程序可能会产生多个job,因为一个程序里面可能会调用多个Action,一个Job里面可能会有多个stage,因为会有多个宽依赖的transformation。每个stage下对应多个task,这些task是可并行的计算单元。在从一个RDD到另一个RDD的一个transformation阶段内,一个Partition对应一个Task。
代码示例:

def simpleSparkProgram(rdd : RDD[Double]): Long ={
 //stage1
 rdd.filter(_< 1000.0)
 .map(x => (x, x) )
 //stage2
 .groupByKey()
 .map{ case(value, groups) => (groups.sum, value)}
 //stage 3
 .sortByKey()
 .count()
 }

Spark根据示例代码划分的Spark 组件:
在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐