Spark理论简明教程

1.Spark简介

1.1定义

是一个数据计算框架,可以实现离线批处理交互式查询实时流计算机器学习图计算

1.2特点

  • 基于内存计算,所以速度会比MR快很多。MR慢的原因之一就是过程中有频繁的磁盘I/O读写,尤其shuffle过程速度更慢。
  • 有大量的RDD算子可以用,开发比较简单直接调API.

1.3Spark与MR

同样都是计算框架,但是因为后者基于内存计算,shuffle过程比后者简单,所以速度更快。

spark的劣势如果一次性针对特别大的数据,比如10E级别,MR非常稳定,即使慢慢算,也会出结果,不会报错。而spark则会内存溢出,或者程序都跑不起来等情况。

1.4Spark与Storm

虽然 Spark stream和storm都可以进行实时计算,但是计算方式完全不同。storm是真正意义上的实时计算,来一条计算一条,而spark更像伪事实。比如一个RDD处理一秒内的数据,等一秒内的数据都包装起来了,再对这个RDD进行操作。

与此同时,再分布式流处理时。storm可以实时调整并行度,而spark不可。

spark的优点也有很多,比如spark是基于一个batch处理的。比一条一条处理的storm吞吐量大得多。其次,spark stream可以无缝和spark其他组件比如Mlib和Greaph。SparkCore等无缝配合。

1.5Spark与Hive

Hive作为离线数仓,除了提供查询功能还提供存储功能。而spark没有存储模块。spark应该是替代hive的查询引擎。因为hive引擎用的MR,所以速度会很慢。

2.Spark原理

2.1SparkCore

  • Spark基础配置
    • SparkConf配置信息
    • SparkContext上下文
    • SparkRPC过程调用
    • ListenserBus事件总线
    • MetricxSystem度量系统
    • SparkEnv环境变量
  • 存储系统
    • 内存
    • 磁盘
  • 计算层
    • 内存管理
    • 任务管理
    • Task管理
    • Shuffle管理
  • 调度原理
    • DAG调度
    • Task调度

2.1.0概述

每个spark程序包含一个Driver程序其中有main函数,然后在集群上并行执行main中的业务代码。

2.1.1Spark基础配置

sparkContext是spark应用程序入口,正常开发调用spark api即可

2.1.2Spark存储系统

优先把数据缓存在内存中,内存不足时写入磁盘。可以远程调用将结果输出到hdfs或者hbase中。

2.1.3Spark调度系统

  • DAGScheduiler
  • 每一个job根据RDD的关系分为多个Stage
  • Stage抽象为Task交给
  • TaskScheduler进行任务调度
  • 主要算法有FIFO和FAIR
    • FIFO:先进先出。这是默认的模式
    • FAIR:作业分组到池,每个池分配不同的权重,任务按权重决定执行顺序。

2.2SparkSQL

Spark支持两种数据抽象

DataFrame

​ 对结构数据的抽象,可以理解为spark的表。

DataSet

​ 数据的分布式集合,由Jvm构建。可以使用map。flatmap等操作函数操作。

RDD

​ 分布式对象集合,提升数据的执行效率。是弹性分布式数据集,他是对数据的映射。RDD会被分区,然后分到多个分区。每个分区分布在集群不同的节点,从而可以让RDD中数据并行操作。在内存不足时,RDD也会被写到节点的磁盘里。该RDD由所分节点处理完后,还可以去第二批节点,继续处理。可以去多批节点,这就是内存上的迭代。如果在该批次某一台节点丢失了数据,Spark会重新根据上一个节点的RDD计算得到新节点的数据。

​ RDD主要有两种操作,Transformating和Action两种操作。

  • Transformation(转换)是在一次迭代中切换成新的RDD,不会立即出结果,有map。filter。flatmap等操作。
  • Action(执行)对已有的RDD计算产生结果,将结果返回Driver或者写入外部,有reduce,SavaAsTextfile等方法。

2.3SparkStreaming

主要是支持对流数据的处理,支持数据的可伸缩和容错处理。

2.5 RDD

rdd是弹性分布式数据集具体可以看SparkRDD.md

2.6 Spark-Shell

shell使用时会自动生成一个sparkcontext (sc)

2.7 Shuffle

某些RDD会调起shuffle操作,其作用是将数据重新分布。结果数据会子啊各个分区重新分组,shuffle通常开销会很大,因为涉及到跨excutor和跨节点复制数据。

以reducebykey为例,首先需要把其他分区中相同key的元素转移到当前分区,方便后续reduce操作。

shuffle后元素顺序不是确定的。需要使用.sort排序每个分区

repartitionAndSortWithinPartitions

重分区的同时,对分区进行排序,比自行组合repartition和sort更高效

sortBy 创建一个全局有序的RDD

会导致混洗的算子有:

**重分区(repartition)**类算子,如: repartition 和 coalesce;

ByKey 类算子(除了计数类的,如 countByKey) 如:groupByKey和 reduceByKey;

Join类算子,如:cogroup和 join.

性能影响

混洗合计大量磁盘I/O,网络I/O.还有序列化操作。

单个任务是内存中执行的,直到放不下溢出时放磁盘,在reduce时会基于目标分区重新排序,并写到一个文件里。reduce到时只读取与任务相关的blocks。

因为一个任务通常有多个stage。为了防止数据丢失时重新shuffle运算,通常全部数据只有运算结束时才会清除。

2.8 RDD持久化

首先需要明白 RDD的血缘关系可以重用但是数据不可以,数据每次使用都会重新计算

这里的数据是指 结果数据

rdd1=map(xxxx)
rdd2=rdd1.flatmap

如图,首先,rdd不存储数据。所以rdd2调用rdd1时,rdd1的数据会重新计算在给rdd2。这就是数据不可复用但血缘可复用。相当于rdd1把自己的计算过程给rdd2,让其重新计算。

所以缓存和持久化保存数据后,rdd2再调用,就可以直接获取数据。

数据 结果 可以持久化或者缓存到内存中,当你持久化了一个RDD,所有的节点都会存储该RDD的一些 分区

后续可以复用,通常会提速10倍。

你可以用persist() 或者 cache() 来标记一下需要持久化的RDD。等到该RDD首次被施加action算子的时候,其对应的数据分区就会被保留在内存里。同时,Spark的缓存具备一定的容错性 – 如果RDD的任何一个分区丢失了,Spark将自动根据其原来的血统信息重新计算这个分区。

另外,每个持久化的RDD可以使用不同的存储级别,比如,你可以把RDD保存在磁盘上,或者以java序列化对象保存到内存里(为了省空间),或者跨节点多副本,或者使用 Tachyon 存到虚拟机以外的内存里。这些存储级别都可以由persist()的参数StorageLevel对象来控制。cache() 方法本身就是一个使用默认存储级别做持久化的快捷方式,默认存储级别是 StorageLevel.MEMORY_ONLY(以java序列化方式存到内存里)。完整的存储级别列表如下:

存储级别含义
MEMORY_ONLY以未序列化的Java对象形式将RDD存储在JVM内存中。如果RDD不能全部装进内存,那么将一部分分区缓存,而另一部分分区将每次用到时重新计算。这个是Spark的RDD的默认存储级别。
MEMORY_AND_DISK以未序列化的Java对象形式存储RDD在JVM中。如果RDD不能全部装进内存,则将不能装进内存的分区放到磁盘上,然后每次用到的时候从磁盘上读取。
MEMORY_ONLY_SER以序列化形式存储RDD(每个分区一个字节数组)。通常这种方式比未序列化存储方式要更省空间,尤其是如果你选用了一个比较好的序列化协议(fast serializer),但是这种方式也相应的会消耗更多的CPU来读取数据。
MEMORY_AND_DISK_SER和MEMORY_ONLY_SER类似,只是当内存装不下的时候,会将分区的数据吐到磁盘上,而不是每次用到都重新计算。
DISK_ONLYRDD数据只存储于磁盘上。
MEMORY_ONLY_2, MEMORY_AND_DISK_2, etc.和上面没有”_2″的级别相对应,只不过每个分区数据会在两个节点上保存两份副本。
OFF_HEAP (实验性的)将RDD以序列化格式保存到Tachyon。与MEMORY_ONLY_SER相比,OFF_HEAP减少了垃圾回收开销,并且使执行器(executor)进程更小且可以共用同一个内存池,这一特性在需要大量消耗内存和多Spark应用并发的场景下比较吸引人。而且,因为RDD存储于Tachyon中,所以一个执行器挂了并不会导致数据缓存的丢失。这种模式下Tachyon 的内存是可丢弃的。因此,Tachyon并不会重建一个它逐出内存的block。如果你打算用Tachyon做为堆外存储,Spark和Tachyon具有开箱即用的兼容性。

Spark会自动持久化一些混洗(shuffle)操作(如:reduceByKey)的中间数据,即便用户根本没有调用persist。这么做是为了避免一旦有一个节点在混洗过程中失败,就要重算整个输入数据。当然,我们还是建议对需要重复使用的RDD调用其persist算子。

如何选择存储级别?

Spark的存储级别主要可于在内存使用和CPU占用之间做一些权衡。建议根据以下步骤来选择一个合适的存储级别:

如果RDD能使用默认存储级别(MEMORY_ONLY),那就尽量使用默认级别。这是CPU效率最高的方式,所有RDD算子都能以最快的速度运行。

如果步骤1的答案是否(不适用默认级别),那么可以尝试MEMORY_ONLY_SER级别,并选择一个高效的序列化协议(selecting a fast serialization library),这回大大节省数据对象的存储空间,同时速度也还不错。

尽量不要把数据吐到磁盘上,除非:1.你的数据集重新计算的代价很大;2.你的数据集是从一个很大的数据源中过滤得到的结果。否则的话,重算一个分区的速度很可能和从磁盘上读取差不多。

如果需要支持容错,可以考虑使用带副本的存储级别(例如:用Spark来服务web请求)。所有的储级别都能够以重算丢失数据的方式来提供容错性,但是带副本的存储级别可以让你的应用持续的运行,而不必等待重算丢失的分区。

在一些需要大量内存或者并行多个应用的场景下,实验性的OFF_HEAP会有以下几个优势:

  • 这个级别下,可以允许多个执行器共享同一个Tachyon中内存池。

  • 可以有效地减少垃圾回收的开销。

  • 即使单个执行器挂了,缓存数据也不会丢失。

  • 删除数据

Spark能够自动监控各个节点上缓存使用率,并且以LRU(最近经常使用)的方式将老数据逐出内存。如果你更喜欢手动控制的话,可以用RDD.unpersist() 方法来删除无用的缓存。

3.Spark运行模式和集群

3.0集群运行模式

local

​ 本地模式,分为local单线程和local-ckuster多线程模式

standalone

​ 集群模式,独立模式,spark用自己的资源调度框架运行。时master/slave模式

yarn

​ 集群模式,有Yarn负责资源管理。spark负责任务调度和计算。

Mesos

​ 集群模式,mesos负责资源管理,spark负责任务调度和计算。

K8s

​ 集群模式,在k8s上运行

3.1集群角色

ClusterManger

​ 集群管理器,在Master进程里。对应用程序申请资源的管理。有local,standalone,yarn。mesos等模式。

Worker

​ 用于执行任务的提交

  • worker节点用注册机像clusterManger汇报executor状态,cpu内存等。
  • 创建executor。这是计算单元。
  • 在executor上执行master分配的task。

yarn模式下,work节点是指NodeManger节点。

executor

​ 执行计算任务的组件,负责Task的运行,可以把数据存储在内存或磁盘中。也能将数据返回Driver。

application

​ 是SparkAPI编写的程序,编写在各个executor上执行的代码。

Driver

​ 负责将job转为tasks,在各个exexutor中协调调度task。

SparkContext

​ spark所有功能的入口,初始化spark所需要的所有组件。负责向master注册等。

3.2调度

DAGScaeduler

​ 面向stage的调度器,负责把DAG拆分为Task,每组Task是stage。

TaskScheduler

​ 负责具体任务的执行,任务调度管理。状态结果跟踪,任务执行,取得结果。

job

​ 多个stage构成,有action操作来触发。一个job包含多个RDD以及作用在RDD上的各种操作算子。

stage

​ DAGScheduler会把DAG分割为依赖的Stage,执行时,chid stage会等待parent stage执行完毕。然后进入下一个阶段。在stage内部,操作时popeline串行执行的。

4.运行流程

  • sparkContext向ClusterManger申请资源
  • clusterManger分配资源,在worker节点创建executor
  • sparkContext发送程序代码和task任务给executor,等结果出来了sparkContext收集结果给driver

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值