一文入门大数据准流式计算引擎 Spark【万字详解,全网最新】

Spark 发展、特点、概述,三大组件:Spark Core、Saprk SQL、Spark Streaming,RDD 算子、RDD 转换和行动操作、RDD 持久化和缓存、检查点机制、宽窄依赖、DAG、Stage,Spark、SQL 发展、概述、特点、dataframe、dataset,Spark Streaming 工作机制、缓存、容错、DStream、常见流式计算和离线计算,Spark 多种部署方式

Spark 简介

Spark 于 2009 年诞生于加州大学伯克利分校 AMPLab,2013 年被捐赠给 Apache 软件基金会,2014 年 2 月成为 Apache 的顶级项目。

相对于 MapReduce 的批处理计算,Spark 基于内存计算,可以带来上百倍的性能提升,因此它成为继 MapReduce 之后,最为广泛使用的分布式计算框架、大数据分析引擎

Spark 特点

  • :采用DAG 执行引擎,支持循环数据流和内存计算,使得 Spark 速度更快,在内存中的速度 是 Hadoop MR 的百倍,在磁盘上的速度是 Hadoop MR 的十倍(官网数据)。
  • 通用:Spark 提供了统一的解决方案。Spark 可以⽤于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)。这些不同类型的处理都可以在同⼀个应用中无缝使用。
  • 易用:Spark 支持 Java、Python、Scala 的 API 和超过 80 种⾼级算法,⽽且⽀持交互式的 Python 和 Scala 的 shell。
  • 兼容:Spark 可以使⽤ Hadoop 的 YARN 和 Apache Mesos 作为它的资源管理和调度器,器,并且不需要任何数据迁移就可以处理所有 Hadoop 支持的数据,包括 HDFS、HBase 和 Cassandra 等。Spark 也可以不依赖于第三⽅的资源管理和调度器,它实现了 Standalone 作为其内置的资源管理和调度框架。

Spark 和 MR 处理任务对比

Spark 组件

Spark Core

Spark Core 实现了 Spark 的基本功能,包含任务调度、内存管理、错误恢复、与存储系统 交互等模块。Spark Core 中还包含 了对弹性分布式数据集(resilient distributed dataset,简称 RDD)的 API 定义。

RDD 算子

为什么有 RDD?

在许多迭代式算法(比如机器学习、图算法等)和交互式数据挖掘中,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。但是, 之前的 MapReduce 框架采用非循环式的数据流模型,把中间结果写入到 HDFS 中,带来了大量的数据复制、磁盘 IO 和序列化开销,且这些框架只能支持一些 特定的计算模式(map/reduce),并没有提供一种通用的数据抽象

RDD 提供了一个抽象的数据模型,让我们不必担心底层数据的分布式特性,只需将具体的应用逻辑表达为一系列转换操作(函数) ,不同 RDD 之间的转换操作之间还可以形成依赖关系,进而实现管道化,从而避免了中间结果的存储,大大降低数据复制、磁盘 IO 和序列化开销,并且还提供了更多的 API 操作!

RDD 介绍
  • RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据抽象,是 Spark 计算的基石,它代表⼀个不可变、可分区、里面的元素可并行计算的集合。
  • RDD 具有数据流模型的特点:自动容错、位置感知性调度和可伸缩性。RDD 允许用户在执⾏多个查询时显式地将⼯作集缓存在内存中,后续的查询能够重⽤⼯作集,这极⼤地提升了查询速度。
  • MR 中对数据是没有进行抽象的,而在 Spark 中对数据进行了抽象,提供⼀些列处理⽅法也就是 RDD,为用户屏蔽了底层对数据的复杂抽象和处理,为⽤户提供了⼀组⽅便 的数据转换与求值方法,好比 Java 中类的封装。

注意 : RDD 本身是不存储数据,而是记录了数据的位置,数据的转换关系(调用什么方法、传入什么函数)!!!

以下是 RDD 源码翻译解读:

RDD 特点

  • 弹性体现:
    1. 存储的弹性:内存与磁盘的自动切换;
    2. 容错的弹性:RDD 的血统(Lineag)会记录 RDD 的元数据信息和转换行为 ,当 RDD 的部分分区数据丢失时,它可以根据这些信息来重新运算并恢复丢失的数据分区。
    3. 计算的弹性:计算出错重试机制;
    4. 分片的弹性:可根据需要重新分片;
  • 分布式:数据存储在大数据集群不同节点上
  • 数据集:RDD封装了计算逻辑,并不保存数据
  • 数据抽象:RDD 是⼀个抽象,需要具体实现
  • 不可变:RDD 封装的计算逻辑不可改变,想要改变只能产⽣新的 RDD
  • 可分区、并行计算

RDD 做了什么

从计算的角度来讲,数据处理过程中需要计算资源(内存 & CPU)和计算模型(逻辑)。执⾏时,需要将计算资源 和计算模型进行协调和整合

Spark 框架在执行时,先申请资源,然后将应⽤程序的数据处理逻辑分解成⼀个⼀个的计算任务。然后将任务分发到已经分配资源的计算节点上, 按照指定的计算模型进行数据计算。最后得到计算结果。

RDD 的转换和行动操作

  • RDD 算子分为两种类型的操作:转换操作和行动操作
  • 转换操作是返回⼀个新的 RDD 的操作,比如 map 和 flatMap
  • 行动操作则是向 Driver 返回结果或将结果写出到外部存在设备,比如 collect 和 saveAsTextFile
  Transformation(转换)算子概述

RDD 中的所有转换都是延迟加载的,它们只是记住这些应⽤到基础数据集上的转换动作,并不会直接计算结果。只有当发生⼀个要求返回结果给 Driver 的动作时,这些转换才会真正运 行。这样可以在 Action 时对 RDD 操作形成 DAG 有向无环图进行 Stage 的划分和并行优化,这这种设计让 Spark 更加有效率地运行! 列举部分算子:

Action(行动)算子概述  

在 RDD 上运⾏计算,并返回结果给 Driver 或写入文件系统, 列举部分算子:

RDD 持久化和缓存

  • Spark 速度非常快的原因之⼀,就是在不同操作中可以在内存中持久化或缓存多个数据集。当持久化某个 RDD 后, 每⼀个节点都将把计算的分片结果保存在内存中,并在对此 RDD 或衍⽣出的 RDD 进行的其他动作中重⽤,这使得后续的动作变得更加迅速!
  • 缓存是 Spark 构建迭代式算法和快速交互式查询的关键。如果⼀个有持久化数据的节点发⽣故障,Spark 会在需要⽤到缓存的数据时重算丢失的数据分区。如果希望节点故障的情况不会拖累我们的执⾏速度,也可以把数据备份到多个节点上。
  • RDD 通过 persist 或 cache 方法可以将前面的计算结果缓存,但是并不是这两个方法被调用时立即缓存,而是触发后面的 action 时,该 RDD 将会被缓存在 计算节点的内存中,并供后面重用。

存储级别

默认的存储级别都是仅在内存存储一份,Spark 的存储级别还有好多种,存储级别在 object StorageLevel 中定义的。

Checkpoint 检查点机制  

Spark 中对于数据的保存除了持久化操作之外,还提供了⼀种检查点的机制,检查点(本质是通过将 RDD 写入 Disk 做检查点)是为了通过血统(lineage)做持久化容错的辅助,lineage 过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题⽽丢失分区,从做检查点的 RDD 开始重做 Lineage,就会减少资源开销。检查点通过将数据写⼊到 HDFS 文件系统实现了 RDD 的检查点功能。

RDD 宽窄依赖

RDD 和 它依赖的父 RDD 的关系有两种不同的类型,

宽依赖(wide dependency/shuffle dependency) :父 RDD 的一个分区被子 RDD 的多个分区依赖(涉及到 shuffle)

窄依赖(narrow dependency):父 RDD 的一个分区只会被子 RDD 的一个分区依赖;

为什么要设计宽窄依赖

对于窄依赖: 窄依赖的多个分区可以并行计算;窄依赖的一个分区的数据如果丢失只需要重新计算对应的分区的数据就可以了。

对于宽依赖: 划分 Stage(阶段)的依据,对于宽依赖,必须等到上一阶段计算完成才能计算下 一阶段。

DAG 生成和划分 Stage
  • DAG 是什么?
    DAG(有向无环图)指的是数据转换执行的过程,有方向,无闭环(其实就是 RDD 执行的流程);原始的 RDD 通过一系列的转换操作就形成了 DAG 有向无环图,任务执行时,可以按照 DAG 的描述,执行真正的计算(数据被操作的一个过程)。
  • DAG 的边界
    开始:通过 SparkContext 创建的 RDD
    结束:触发 Action,一旦触发 Action 就会形成一个完整的 DAG

DAG 划分 Stage

  • 一个 Spark 程序可以有多个 DAG(有几个 Action,就有几个 DAG)。
  • 一个 DAG 可以有多个 Stage(根据宽依赖/shuffle 进行划分)。
  • 同一个 Stage 可以有多个 Task 并行执行(task 数=分区数,如上图,Stage1 中 有三个分区 P1、P2、P3,对应的也有三个 Task)。
  • 可以看到这个 DAG 中 reduceByKey 操作是一个宽依赖,Spark 内核会以此为边界将其前后划分成不同的 Stage。 同时在图 Stage1 中,从 textFile 到 flatMap 到 map 都是窄依赖,这几步操作可以形成一个流水线操作,通过 flatMap 操作生成 partition 不用等待整个 RDD 计算结束,可以直接进行 map 操作,这样大大 提高了计算的效率。

Spark SQL

Spark SQL 发展(精彩)

Spark SQL 是构建在 SparkCore 基础之上的⼀个基于 SQL 的计算模块。 SparkSQL 的前身叫【Shark】,最开始 Shark 的底层代码优化、sql 的解析、执行引擎等完全基于 Hive(Shark On Hive),Hive 实现了 SQL on Hadoop,使用 MapReduce 执行任务,但是使用 MapReduce 做计算(Hive On MR),使得 Hive 的查询延迟比较高,而 Shark 改写 Hive 的物理执行计划,使用 Shark 代替 MapReduce 物理引擎(Hive On Shark),使用列式内存存储,使得 Shark 执行速度比 Hive 快,然而 Shark 执行计划的生成严重依赖 Hive(Shark On Hive On Shark),想要增加新的优化非常困难; 并且 Hive 是进程级别的并行,Spark 是线程级别的并行,所以 Hive 中很多线程不安全的代码不适用于 Shark,所以在 15 年中旬的时候,Shark 负责⼈,将 Shark 项⽬结束掉,重新独⽴出来的⼀个项⽬,就是 SparkSQL,不再依赖 Hive,此后逐渐的形成两条互相独立的业务:SparkSQL 和 Hive-On-Spark。

如果说 Hive 是将 SQL 转化为 MR,那么 SparkSQL 是将 SQL 转换成 RDD+优化执行,因为我们直接操作 RDD 需要编程实现(学习成本),有了 SQL 我们即使不懂编程也可以实现 RDD 计算!

Spark SQL 概述

Spark SQL主要用于结构化数据(数据分为结构化数据、半结构化数据、非结构化数据)RDD 主要用于处理非结构化、半结构化、结构化数据。与 RDD API 编程式操作不同,Spark SQL 可以使用 SQL 完成数据分析计算,Spark SQL 提供的接口为 Spark提供了有关数据结构和正在执⾏的计算的更多信息。在内部,Spark SQL 使⽤这些额外的信息来执⾏额外的优化。有几种与 Spark SQL 交互的⽅法,包括 SQL 和 Dataset API。计算结果时,将使⽤相同的执⾏引擎,这与⽤于表示计算的 API/语⾔⽆关。这种统⼀意味着开发⼈员可以轻松地在不同的 API 之间来回切换,基于 API 的切换提供了表示给定转换的最⾃然的⽅式。

Spark SQL 特点

  • 集成性
  • 统一性
  • 集成 Hive
  • 支持多种数据源

Spark SQL 数据模型 DataFrame 和 Dataset

我们可以通过两种方式使用 Spark,一种是命令式,使用 Spark shell 编程操作 RDD,另一种是通过 SparkSQL 的数据模型 DataFrame 和 Dataset

  • DataFrame 和 Dataset 可以理解为是⼀张 mysql 中的⼆维表,表有什么?表头,表名,字段,字段类型。RDD 其实说白了也是⼀张二维表,但是这张二维表相比较于 DataFrame 和 Dataset 却少了很多东西,比如表头,表名,字段,字段类型,只有数据和操作数据的方法
  • DataFrame 是 1.3 的时候出现的,Dataset 是在 spark 1.6.2 出现的,**早期的时候 DataFrame 叫 SchemaRDD,SchemaRDD 和 RDD 相比,就多了 Schema,所谓元数据信息。**相比 DataFrame,Dataset 提供了编译时类型检查,对于分布式程序来讲,提交⼀次作业要编译、打包、上传、运行,到提交到集群运行时才发现错误,很麻烦,这也是引⼊ Dataset 的⼀个重要原因!
  • ⼀般的,将 RDD 称之为 Spark 体系中的第一代编程模型;DataFrame 比 RDD 多了⼀个 Schema 元数据信息,被称之为 Spark 体系中的第⼆代编程模型;Dataset 吸收了 RDD 的优点(强类型推断、函数式编程)和 DataFrame 中的优化(SQL 优化引擎、内存列存储),成为 Spark 的最新⼀代的编程模型。

如何进行 SparkSQL 编

  • Spark Core 中,如果想要执行应用程序,需要首先构建上下文环境对象 SparkContextSpark SQL 其实可以理解为对 Spark Core 的⼀种封装,不仅仅在模型上进行了封装,上下文环境对象也进行了封装。
  • 在老的版本中,SparkSQL 提供两种 SQL 查询起始点:⼀个叫SQLContext,⽤于 Spark 自己提供的 SQL 查询; ⼀个叫HiveContext,⽤于连接 Hive 的查询。
  • SparkSession 是 Spark 最新的 SQL 查询起始点,实质上是 SQLContext 和 HiveContext 的组合,所以在 SQLContex 和 HiveContext 上可⽤的 API 在 Spark Session 上同样是可以使⽤的。
  • SparkSession 内部封装了 SparkContext,所以计算实际上是由 sparkContext 完成的。 构建 SparkSession 需要依赖 SparkConf 或者 SparkContext,可以使⽤⼯⼚构建器(Builder ⽅式)模式创建 SparkSession。

Spark Streaming

简介

  • Spark Streaming 是 Spark 提供的对实时数据进行**流式计算(实时计算)**的组件。提供了用来操作数据流的 API,并且与 Spark Core 中的 RDD API 高度对应。
  • 从计算的延迟上⾯,又可以分为纯实时流式计算和准实时流式计算,SparkStreaming 属于准实时计算框架
  • 所谓纯实时的计算,指的是来⼀条记录(event 事件),启动⼀次计算的作业;离线计算指的是每次计算非常大的⼀批(比如几百 G,好几个 T)数据;准实时则是介于纯实时和离线计算之间的⼀种计算方式,那就是微批处理,即把大量数据微分成多小批进行计算,近似看成流计算。

流式计算特点

  • 数据是无界的(unbounded)
  • 数据是动态的
  • 计算速度快
  • 计算不止一次
  • 计算不能终止

离线计算特点:

  • 数据是有界的(Bounded)
  • 数据静态的
  • 计算速度通常较慢
  • 计算只执⾏⼀次
  • 计算终会终⽌

常见流式计算和离线计算框架

离线

  • mapreduce
  • spark-core
  • flink 的 dataset

流式

  • storm  第⼀代的流式处理框架
  • sparkStreaming(其实是为微批处理)第二代的流式处理框架
  • flink 的 datastream  第三代的流式处理框架

SparkStreaming 的基本工作原理

SparkCore 的数据模型是 RDD,SparkSQL 数据模型是 DataFrame 和 DataSet,SparkStreaming 的数据模型是 DStream,DStream 和 RDD 一样,是一种高级抽象,它基于内存处理连续的数据流,本质上还是 RDD 的基于内存的计算。

  • 接收实时输入数据流,然后将数据拆分成多个 batch,比如每收集 1 秒的数据封装为⼀个 batch,然后将每个 batch 交给 Spark 的计算引擎进行处理,最后会⽣产出⼀个结果数据流,其中的数据,也是由一个一个的 batch 所组成的。
  • DStream,英⽂全称为 Discretized Stream,中文翻译为“离散流”,它代表了⼀个持续不断的数据流。DStream 可以通过输入数据源来创建,比如 Kafka、Flume、ZMQ 和 Kinesis;也可以通过对其他 DStream 应用高阶函数来创建,比如 map、reduce、join、window。
  • **DStream 的内部,其实是一系列时间上连续的 RDD。DStream 中的每个 RDD 都包含了⼀个时间段内的数据。
  • 对 DStream 应⽤的算子,比如 map,其实在底层会被翻译为对 DStream 中每个 RDD 的操作。比如对⼀个 DStream 执行⼀个 map 操作,会产生⼀个新的 DStream。但是,在底层,其实是对输入 DStream 中每个时间段的 RDD,都来⼀遍 map 操作,然后**⽣成的新的 RDD**,即作为新的 DStream 中的那个时间段的⼀个 RDD。

SparkStreaming 的缓存

SparkStreaming 的缓存,说白了就是 DStream 的缓存,DStream 的缓存就只有⼀个⽅⾯,那就是 DStream 对应的 RDD 缓存,RDD 如何缓存?rdd.persist(),所以 DStream 的缓存说⽩了就是 RDD 的缓存,使⽤ persist()指定,并指定持久化策略,⼤多算⼦默认情况下,持久化策略为 MEMORY_AND_DISK_SER_2

SparkStreaming 的容错

  • 每⼀个 Spark Streaming 应⽤,正常来说都是要 7*24 ⼩时运转的,这也是实时计算程序的特点。因为要持续不断的对数据进⾏计算,因此对实时计算应⽤的要求必须进行容错保底
  • Spark Streaming 程序就必须将足够的信息 checkpoint 到容错的存储系统上,从⽽让它能够从失败中进行恢复。有两种数据需要被 checkpoint:
  • 元数据 checkpoint:将定义了流式计算逻辑的信息,保存到容错的存储系统上,⽐如 HDFS。当运行 Spark Streaming 应⽤程序的 Driver 进程所在节点失败时,该信息可以⽤于进⾏恢复。元数据信息包括了: 创建 Spark Streaming 应⽤程序的配置信息,比如 SparkConf 中的信息。 定义了 Spark Stream 应⽤程序的计算逻辑的DStream 操作信息。 定义了那些 job 正在排队,还未处理的 batch 信息
  • 数据 checkpoint:将实时计算过程中产生的 RDD 的数据保存到可靠的存储系统中。 对于一些将多个 batch 的数据进⾏聚合的,有状态的 transformation 操作,这是⾮常有⽤的。在这种 transformation 操作中,生成的 RDD 是依赖于之前的 batch 的 RDD,这会导致随着时间的推移,RDD 的依赖链条变得越来越长。 要避免由于依赖链条越来越长,导致的⼀起变得越来越长的失败恢复时间,有状态的 transformation 操作执⾏过程中间产⽣的 RDD,会定期地被 checkpoint 到可靠的存储系统上,比如 HDFS。从而削减 RDD 的依赖链条,进而缩短失败恢复时,RDD 的恢复时间。

DStream 操作

DStream 上的操作与 RDD 的类似,分为以下两种:

  • Transformations(转换)

**无状态转换:**每批次处理不依赖于之前批次的数据

**有状态转换:**当前批次的处理需要使用之前批次的数据或者中间结果,有状态转换包括基于追踪状态变化的转换(updateStateByKey)和滑动窗口的转换:

  • Output Operations(输出)/Action

Output Operations 可以将 DStream 的数据输出到外部的数据库或文件系统。 当某个 Output Operations 被调用时,spark streaming 程序才会开始真正的 计算过程(与 RDD 的 Action 类似)。

MLlib

提供常见的机器学习(ML)功能的程序库。包括分类、回归、聚类、协同过滤等,还提供了模型评估、数据导入等额 外的⽀持功能

Graphx

GraphX 在 Spark 基础上提供了一站式的数据解决⽅案,可以⾼效地完成图计算的完整流⽔作业。GraphX 是⽤于图 计算和并⾏图计算的新的(alpha)Spark API。通过引⼊弹性分布式属性图(Resilient Distributed Property Graph),⼀种顶点和边都带有属性的有向多重图,扩展了 Spark RDD

Spark 多种部署模式

  • Local 多⽤于本地测试,如在 eclipse,idea 中写程序测试等。
  • Standalone 是 Spark ⾃带的⼀个资源调度框架,它⽀持完全分布式。
  • Yarn ⽣态圈⾥⾯的⼀个资源调度框架,Spark 也是可以基于 Yarn 来计算的。
  • Mesos 资源调度框架,与 Yarn 类似。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计