Spark简介

Spark的简介

Spark 萌芽于加州大学伯克利分校,基于底层Mesos(Nexus)跨平台调度器构建,可视为Hadoop的内存变体,主要的区别有:

  • 有向无环图(DAG):Spark应用程序形成一个有向无环图,而Mapreduce则是严格的两阶段并行计算。
  • 内存分析:Spark最核心的技术在于弹性分布式数据集(RDDs),这些数据集缓存在内存中,每个RDD还存储血统谱系图用于容错,这个谱系图包含了一系列转换,但需要部分或全部执行转换才能重新生成RDD,RDDs加速了迭代和交互式应用程序的性能:
    • 迭代应用程序:迭代时可以重复使用RDD缓存,无须每次从磁盘读取缓存。
    • 交互式应用程序:可以对同一个RDD运行多重查询
      RDDs也可以作为文件在HDFS和其他存储上持久化。因此,Spark需要依赖Hadoop分布才能使用HDFS。
  • 数据优先:RDD抽象是Spark API最主要的数据。通过操作RDD生成另一个RDD来执行计算,一次类推。而Mapreduce正好相反,只是在键值对的基础上分析数据集,重点在于计算。
  • 简洁的API:Spark实在Scala语言中实现的,Spark默认API也支持Scala。Scala的函数式抽线天然适合RDD转换,如map,groupBy,filter等。此外,应用匿名函数或者lambda抽象可以简化标准的数据操作任务。
  • REPL分析:Scala允许Scala解释器当作交互式数据分析工具使用。例如,在实现完整分析之前,可以用Scala shell命令解释器了解数据集的分布和特征。

Spark相关的项目:

  • Spark SQL(前身Shark)支持在Spark上执行SQL查询。这项功能与DataFrame抽象相结合,将Spark打造成为一款数据分析的强大工具。
  • MLlib是一套备受欢迎的机器学习和数据挖掘算法。另外,它包含有抽象可用于辅助特征提取。
  • Spark Streaming将Spark转化为实时流处理系统,将输入视为微批处理,同时保留熟悉的Spark语法。、、

Spark的安装

Spark

Spark控制进程

守护进程描述
Driver(驱动程序)包含SparkContext实例的应用程序入口
Master(主进程)负责调度和资源编排
Worker(子进程)负责节点状态和运行执行器
Executor(执行器)根据作业分配,负责执行该作业派发的任务
  • 每一个Spack应用程序都会用到一个SparkConf类型的配置对象。通过这个配置提供集群部署的应用程序名称和JAR。
  • 通过SparkContext对象与Spark集群保持连接,该对象以SparkConf对象作为输入。驱动程序用于创建SparkContext对象。SparkContext也用于创建输入RDD。
  • 每一个RDD对象都有一组转换函数,在应用一个操作后返回新的RDD。
  • Spark应用程序包含转换操作和行动操作。行动通常是触发执行的输出操作-Spark作业只在执行输出行动时才提交执行。换而言之,Spark的转换懒惰无比,需要对其施加行动才可以完成转换。

Spark分层执行结构

实体(Entity)描述
Application(应用程序)SparkContext的一个实例
Job(作业)一个行动后执行的一组阶段
Stage(阶段)在shuffe内的一组转换
Task set(任务组)来自同一组阶段的任务组
Task(任务)一个阶段里的执行单元

SparkContext

RDDs创建

SparkContext提供的RDD创建方法

Signature(函数签名)描述
parallelize[t](seq: Seq[t]):RDD[t]将一个Scala集合转换为一个RDD
range(start: Long,stop:Long,step:Long):RDD[Long]创建一个RDD[Long],从start到stop(不包含stop),以step为步长增加元素
hadoopFile[K,V](path:String,inputFormatClass:Class[_ <:InputFormat[K,V]],keyClass:Class[K],valueClass:Class[V]):RDD[(K,V)]返回一个RDD用于path上的一个Hadoop文件,参数为K,V,并用inputFormatClass进行读取
textFile(path:String):RDD[String]返回一个RDD用于path上的一个Haoop文件。在后台,用TextInputFormat作为inputFormatClass,LongWriteable为keyClass,而Text为valueClass,调用hadoopFile()。在这种情况下Key是文件中的位置,而Value是一行
sequenceFile[K,V](path:String,keyClass:Class[K],valueClass:Class[V] ):RDD[(K,V)]返回一个RDD用于path上的一个Hadoop SequenceFile。在内部,将SequenceFileInputFormat作为inputFormatClass传递,调用hadoopFile()
newAPIHadoopFile[K,V,F<: NewInputFormat[K,V]](path:String,inputFormatClass:Class[F], keyClass:Class[K], valueClass:Class[V]):RDD[(K,V)]使用Hadoop版本中的Hadoop API返回一个RDD用于Path上的一个Hadoop文件,参数为K,V和F
wholeTextFile(path: String):RDD[(String, String)]返回一个RDD用于path上的全部Hadoop文件。在后台,用String作为Key和Value,而WholeTextFileInputFormat作为InputFormatClass。Key是文件路径,而Value是文件的整个内容。如果文件很小,可用此方法。如果文件较大,使用textFile()
union[T](rdds: Seq[RDD[T]]):RDD[T]返回一个RDD,它是同一类型的所有输入RDD的并集

每个函数返回一个具有关联对象类型的RDD,例如,parallelize()返回一个ParallelCollectionRDD,而textFile()返回一个HadoopRDD。

外部依赖关系

由于Spark的分布式特性,Spark任务是跨多个Worker节点进行并行处理的。通常,数据(RDDs)和代码(如闭包)由Spark发出;但在某些情况下,任务代码可能要求访问外部文件或Java库。SparkContext也用于处理这些外部依赖关系
SparkContext依赖关系处理功能

Signature(函数签名)描述
addFile(path:String):Unit将path上存在的文件下载到每个节点。可以通过SparkFiles.get(filename:String)访问该文件。除了指向本地或HDFS位置,path还可以指向远程HTTP/FTP位置
addJar(path:String):Unit添加位于path上的文件作为一个JAR依赖关系,用于被SparkContext执行的所有任务

创建共享变量

Spark转换操作worker机器上的数据独立副本,因此它们之间不存在共享状态。在某些情况下,在workers和驱动程序之间可能需要共享某些状态,例如,如果需要计算一个全局值。SparkContext提供两种类型的共享变量:

  • 广播变量:顾名思义,广播变量是数据的只读副本,由驱动程序向worker任务进行广播,例如共享大变量的一个副本。Spark默认发出一个阶段中每个任务所需的数据。在执行每个任务之前,这个数据进行序列化和反序列化。另一方面,广播变量中的数据通过有效的P2P通信传播,并以反序列化的形式缓存。因此,只有在一个作业中跨多个阶段需要时,广播变量才大有作为。
Signature(函数签名)描述
broadcast(v: T): Broadcast[t]广播v到所有节点,并返回一个广播变量引用。在任务中,通过引用对象的value属性访问此变量的值。创建广播变量后,请勿在worker中使用原始变量v
  • 累加器:支持关联函数的变量。主要特征是,在Worker任务中仅能写入累加器,而且只有驱动程序可以读取它们的值。因此累加器用于实现计数器或者操作允许”+=“和/或”add“运算的对象非常方便。
Signature(函数签名)描述
accumulator[T](initialValue: T):Accumulator[T]返回T类型的累加器。任务可以直接引用它,并执行add和+=运算。只有驱动程序可以返回累加器value属性来读取它的值
accumulatorT:Accumulator[T]附加name参数让一个累加器可以在UI中显示。
accumulableCollectionR,T:Accumulable[R,T]返回一个累加器,用于一个R类型的Collection。R应该实施+=和++=运算。标准选择包括mutable.HashSet,mutable.ArrayBuffer和mutable.HashMap

作业执行

SparkContext也负责将作业提交给调度器,这个过程是透明的。每次调用RDD操作时都会提交这些作业。一个作业分成几个阶段,然后分解成数个任务。这些任务随后又分发给各个worker。

RDD

Spark的核心为弹性分布式数据集(RDDs)。Spark应用程序中几乎所有的数据都存放在RDD中。
来自外部数据源或多个数据源的数据,首先被摄取并转换为RDD,接着将RDD转换成潜在的其他一系列RDD,最后再写入外部数据池或多个数据池。

RDD的本质是将数据分区(Partition)封装起来,犹如一个信封。每个RDD的持久化级别是可配置的;默认的行为是再失败时重新生成。保留血统信息——即RDD所依赖的父RDD——可以让RDD重新生成。RDD是Spark中最重要的部分:应用程序通过转换或执行RDDs才取得进展。RDD基础类提供有简单的转换方法(map, filter)等。RDD派生类在此基础上,通过扩展和实现三种主要方法来构建:compute(),getPartitions()和getDependencies()。

RDD特殊用法示例

RDD类型描述
CartesianRDD对两个RDD进行笛卡尔乘积操作而取得的结果
HadoopRDD表示存储在任何Hadoop兼容存储区中的数据:本地FS,HDFS,S3和HBase
JdbcRDD包含通过一个JDBC连接执行一个SQL查询的结果
NewHadoopRDD与HadoopRDD相同,但使用新的Hadoop API
ParallelCollectionRDD包含Scala Collections对象
PipedRDD将一个RDD的内容输送给一个外部命令,例如bash命令或Python脚本
UnionRDD将多个RDD封装,并将封装后的这些RDD视为单个RDD

RDD也可以通过隐式转换进行转换

RDD转换类描述
DoubleRDDFunctions可应用于Double型RDD的函数。这些函数包括mean(),variance(),stdev()和histogram()
OrderedRDDFunctions可应用于键值对RDD的排序函数。这些函数包括sortByKey()在内
PairRDDFunctions可应用于键值对RDD的函数,这些函数包括combineByKey(),aggregateByKey(),reduceByKey()和groupByKey()在内
SequenceFileRDDFunctions将键值对RDD转换为Hadoop SequenceFiles的函数。例如,saveAsSequenceFile()

持久化

RDD持久化级别探讨了CPU,IO和内存开销之间的不同点。通过调用每个RDD提供的persist()方法来设置这个值。cache()方法默认为MEMORY_ONLY的持久化级别。持久化由BlockManager处理,BlockManager内部维护一个内存存储区和一个磁盘存储区。RDD也可应用checkPoint()函数来做检查点,与缓存不同的是,检查点直接将RDD保存到HDFS,并且不保存血统信息。

存储级别描述
NONE默认持久化级别,失败后,RDD重新生成
DISK_ONLYRDD持久存储在磁盘上
DISK_ONLY_2与前面相同,但是存储在两台机器上
MEMORY_ONLYRDD以非序列化形式持久存储在内存中。内存空间不足时,分区需要重新计算
MEMORY_ONLY_2与前面相同,但是在两台机器上
MEMORY_ONLY_SERRDD以序列化的形式持久存储在内存中
MEMORY_ONLY_SER_2RDD以序列化的形式持久存储在两台机器的内存中
MEMORY_AND_DISKRDD首先以非序列化格式持久存储在内存中,内存空间不足时,未存储在内存的分区被溢出到磁盘
MEMORY_AND_DISK_2与前面相同,但是在两台机器上
MEMORY_AND_DISK_SER与前面相同,但分区以序列化存储
MEMORY_AND_DISK_SER_2与前面相同,但是在两台机器上
OFF_HEAP将RDD转移到Alluxio,一个内存数据存储,这大大减少了Worker JVM的内存占用和频繁的GC问题。

转换

应用程序通过转换RDD才能取得进展,这些转换可分为四大类

  • 映射:通过调用用户定义的函数,将输入RDD转换为输出RDD。大多数情况下,在数据点数量方面,输出RDD与输入RDD相比,前者数据点数量较小或相当。
  • 变化算子可以增加或减少RDD中的分区数,或者执行RDD的裂变或聚变
  • 键值转换:仅适用于具有键值对的RDD,调用返回二元组的map函数,通常会创建这些键值对。
  • 混合算子:执行各种任务,例如对RDD中的元素抽样
转换(映射)描述
mapU: RDD[U]函数式编程的标准map函数,调用用户提供的funtion作用于输入RDD中的每一个数据点,以创建相同长度的输出RDD
flatMapU:RDD[U]与map相同,但是使RDD扁平化,因此输出的大小可能与输入RDD的大小不同
mapPartitionsU:RDD[U]调用传递的function作用于RDD中的每个分区。与之相对的,调用标准map()则是作用于每个数据点。提供的函数function应该能够以分区中数据点的迭代器作为输入。因为它减少了函数调用的次数,这比map()更有效率。
mapPartitionsWithIndexU:RDD[U]与mapPartitions()类似,但与迭代器一起,该函数也应该接受一个分区索引。如果逻辑需要跟踪正被处理的分区的索引,这是非常有用的
filterU:RDD[U]过滤掉符合特定条件的值。为此,提供的function需要返回与给定条件对应的布尔值
转换(变化)描述
coalesce(numPartitions: Int, shuffle: Boolean): RDD[T]减少一个RDD中的分区数。在后台,将分区作为一个集体,有逻辑地合并分区。将shuffle设置为false,确保能够合并分区。而将shuffle设置为true时,会让使用哈希分区的shuffle对RDD进行强制的物理上的重新分区。这也意味着可以通过这种机制减少和增加分区的数量
repartition(numPartitions:Int):RDD[t]总是强制执行shuffle,以此来增加或减少RDD中的分区数。在后台,它调用coalesce(),并将shuffle设置为true。
union(other:RDD[T]):RDD[T]返回另一个RDD,是一个RDD与传递的RDD的并集。由UnionRDD具体实现返回的RDD
intersection(other: RDD[T]): RDD[T]返回调用RDD和传递RDD的交集
转换(键值)描述
转换(混合)描述

Spark的作业是由行动开启执行的。每个行动要么是外部数据存储区的数据出口点,要么是驱动程序的入口点。在后台,没个行动调用SparkContext实例来调度其执行。与转换类似,这些行动因RDD类型而异。

行动描述

Spark是一个函数式的大数据处理框架,其中RDD是不可变的数据集合,可进行转换去实现应用程序逻辑。应用程序在大多数情况下是无边界效应的:行动的次数通常小于转换次数。而转换是非常懒惰的,仅在调用下游的行动时才触发转换。

RDD时构成Spark的夯实基石,而且RDD也充当容错,数据摄取和存储以及转换的单元。这些数据与转换、行动和少量其他原语相结合,可以用来整合几乎任何易并行应用程序。Spark让你能够专注于分析,同时由底层引擎处理所有分布式,最大限度的提高生产力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值