Spark 学习笔记

2018-05-15
7分钟阅读时长

Spark 概述

本文为在学习厦门大学 MOOC 课程《大数据技术原理与应用》时所记重点笔记,顺序按照课程顺序

Spark 与 Scala

Spark 为一门用 Scala 开发的大数据框架,成名类似于 Hadoop,Spark 在 2014 年刷新了 Hadoop 之前保持的 1TB 数据基准排序的记录,到现在成为了一个基于内存计算的大数据并行计算框架,可用于构建大型的、低延迟的数据分析应用。

Spark 特点

  • 运行速度快:使用 DAG 执行引擎来进行作业调度,效率要比 MapReduce 高效的多
  • 容易使用:支持多种编程方式
  • 通用性:Spark 提供了完整而强大的技术栈
    • 内存计算 Spark Core
    • 包括 SQL 查询分析 Spark SQL
    • 流式计算 Spark Streaming
    • 机器学习 Spark MLib
    • 图算法 GraphX
  • 运行模式多样

Scala 语言是一门现代的多范式编程语言(比如函数式、面向对象、过程式),平滑的集成了面向对象和函数式编程两种风格可以运行于 Java 平台(JVM)之上。

Scala 特性

  • 强大的并发性,支持函数式编程,支持分布式系统
  • 语法简洁,提供优雅 API
  • Scala 兼容 Java,且能融入到 Hadoop 生态圈
  • 提供 REPL(交互式解释器),提高开发效率

Spark 与 Hadoop 的对比

Hadoop 的缺点

  • 表达能力有限:不是所有应用都能用 Map 和 Reduce 表达
  • 磁盘 IO 开销较大
  • 延迟高
  • 任务之间衔接涉及到 IO 开销
  • 前一个任务完成前其他任务无法开始。难以胜任复杂、多阶段的任务计算

Spark 相比 Hadoop MapReduce 的优点

  • 计算模式属于 MapReduce 但提供多种数据集操作类型是编程模型更灵活
  • Spark 提供内存计算,迭代计算不需要读写磁盘
  • Spark 基于 DAG 任务调度机制

Spark 生态系统

在实际应用中,大数据处理包括三个类型:

  • 复杂的批量处理,数十分钟到几小时。MapReduce
  • 基于历史数据的交互式查询,数十秒到数分钟。Cloudera Impala
  • 基于实时数据流处理,毫秒到数秒之间。Storm

由此带来的问题:

  • 不同场景输入输出数据无法做到无缝共享
  • 不同软件需要不同的开发和维护,较高的使用成本
  • 比较难对同一个集群中的各个系统进行统一的资源协调分配

Spark 设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一整套生态系统 Spark 可以部署在 YARN 之上,提供一站式的数据解决方案 Spark 所提供的生态系统足以应对上述三种场景 Spark 生态系统已成为 BDAS(伯克利大学数据实验室软件栈) 的重要组成 BDAS 架构 Spark 组件应用场景

Spark 运行架构

基本概念

  • 弹性分布式数据集(RDD,Resillient Distributed Dataset)是分布式内存的抽象概念,提供了一种高度受限的共享内存模型
  • 有向无环图(DAG)反映了 RDD 之间的依赖关系
  • Executor,是运行在工作节点的一个进程,负责运行 Task
  • Application,用户编写的 Spark 应用程序
  • Task,运行在 Executor 之上的工作单元
  • Job,一般一个 Application 包含多个 Job,一个 Job 包含多个 RDD 及作用于相应 RDD 上的各种操作
  • Stage,是 Job 调用的基本单位,一个 Job 会分为多组 Task,每组 Task 被称为 Stage,或者称为 TaskSet,代表了一组关联的、相互之间没有 Shuffle 依赖关系的任务组成的任务集

Spark 基本架构设计

Spark 基本架构图

  • Cluster Manager,集群资源管理器,负责对整个 Spark 应用程序来进行集群资源管理分配和调度。可以自带或 Mesos 或 YARN
  • Work Node,运行作业任务的工作节点
  • Driver Program,每个应用的任务控制节点,生成 DAG,对 DAG 进行分成多个阶段,对阶段进行拆解,吧任务分给相关具体的 Executor 执行都是由 Driver 执行
  • Executor,负责每个工作节点上具体任务执行的进程

该架构设计与 Hadoop MapReduce 相比优点

  • 利用多线程来执行具体的任务减少任务的启动开销
  • Executor 中有一个 BlockManager,会将内存和磁盘共同视为存储设备,有效减少 IO 开销

Spark 中各种概念之间的相互关系

Spark 中各种概念之间的相互关系 Spark 中各种概念之间的相互关系

Spark 运行基本流程

Spark 运行基本流程

  1. 为应用构建起基本的运行环境,即由 Driver 创建一个 SparkContext 进行资源的申请、任务的分配和监控
  2. 资源管理器为 Executor 分配资源,并启动 Executor 进程,进程会汇报资源的使用情况
  3. SparkContext 根据 RDD 的依赖关系构建 DAG 图,DAG 图提交给 DAG Scheduler 解析成 Stage,然后吧一个个 TaskSet 提交给底层调度器 Task Scheduler 处理;Executor 主动向 SparkContext 申请 Task,Task Scheduler 将 Task 发放给 Executor 运行并提供应用程序代码
  4. Task 在 Executor 上运行把执行结果反馈给 TaskScheduler,然后反馈给 DAGScheduler,运行完毕后写入数据并释放所有资源

Spark 运行架构特点

  • 每个 AppIication 都有自己专属的 Executor 进程,并且该进程在 AppIication 运行期间一直驻留。Executor 进程以多线程的方式运行 Task
  • Spark 运行过程与资源管理器无关,只要能够获取 Executor 进程并保持通信即可
  • Task 采用了数据本地性和推测执行等优化机制

RDD

RDD 基本概念

设计背景:许多迭代式算法(比如机器学习)和交互式数据挖掘工具,共同之处是,不同计算阶段之间会重用中间结果,目前 MapReduce 框架都是吧中间结果写入到磁盘中带来非常大的磁盘 IO 开销和序列化的开销。RDD 就是为了满足这种需求而出现,它提供了一个抽象的数据结构,将应用逻辑表达式进行一些列的转换。不同的 RDD 之间的转换操作形成以依赖关系(DAG 图),可以实现管道化,一个 RDD 的结果可以作为下一个 RDD 的输入,避免中间数据存储

RDD 概念:一个 RDD 就是一个分布式对象集合,本质上是一个只读的分区记录集合,毎个 RDO 可分成多个分区,毎个分区就是一个数据集片段,并且一个 RDD 的不同分区可以被保存到集群中不同的节点上,从而可以在集群中的不同节点上进行并行计算。 RDD 提供了一种高度受限的内存共享模型,即 RDD 是只读的记录分区的集合,不能直接修改,只能基于稳定的物理存储中的数据集创建 RDD,或者通过在其他 RDD 上执行确定的转换操作(如 map、join、group by)而创建得到新的 RDD

RDD 提供了两种操作来支持常见的数据运算:

  • 转换(Transformation):转换接口非常简单,类似 map、filter 这种粗粒度的数据转换,而不能对某个数据项进行修改(不适合网页爬虫)
  • 动作(Action)

RDD 典型执行过程

RDD 执行实例

  1. RDD 读入外部数据源进行创建数据,根据数据大小创建不同分区,不同分区放到不同数据节点上
  2. RDD 经过一系列转换操作,每一次都会产生不同的 RDD 供给下一个转换使用,不计算结果,只记录轨迹
  3. 最后一个 RDD 经过动作操作计算产生结果
  4. 这一系列处理成为一个 Lineage(血缘关系)反映了不同 RDD 之间的依赖关系,即 DAG 拓扑排序的结果

RDD 特性

  • 高效的容错性。容错机制:血缘关系的设计方式使得 RDD 天生具有容错性,当一个 RDD 分区出现错误,只需要往上层节点追溯并再次转换即可
  • 中间结果持久化到内存:数据在内存中的多个 RDD 操作之间进行传递,降低磁盘开销
  • 存放的数据可以是 Java 对象,避免了不必要的对象序列化和反序列化

RDD 的依赖关系和运行过程

Spark 通过分析各个 RDD 的依赖关系生成了 DAG 图再通过分析各个 RDD 中的分区之间的依赖关系(宽依赖、窄依赖)来决定如何划分 Stage

  • 窄依赖:表现为一个父 RDD 的分区对应于一个子 RDD 的分区或者多个父 RDD 的分区对应于一个子 RDD 的分区
  • 宽依赖:一个父 RDD 的一个分区对应于一个子 RDD 的多个分区

具体划分方法

  • 在 DAG 中进行反向解析,遇到宽依赖就断开(存在 Shuffle)
  • 遇到窄依赖酒把当前的 RDD 加入 Stage
  • 将窄依赖尽量划分在同一个 Stage 中,可以实现流水线计算从而使得数据可以直接在内存中进行交换

Stage 划分过程 如图可以看出,RDD A 和 B 之间是宽依赖,所以 A 被单独划分为一个 Stage 1,CDFE 之间都是窄依赖,可以直接划分成一个 Stage 2 构成流水化作业,之后 B 到 G 是窄依赖,F 到 G 为宽依赖,所以最后根据划分方法总共划分为三个 Stage

Stage 的类型

  • ShuffleMapStage:不是最终的 Stage,在他之后还有其他的 Stage,所以它的输出一定要经过 Shuffle 过程,并作为后续 Stage 的输入。这种 Stage 是以 Shuffle 为输出边界(存在宽依赖断开),其输入边界可以是从外部获取数据,也可以使另一个 ShuffleMapStage 的输出其输出可以使另一个 Stage 的开始
  • ResultStage:没有输出,而是直接产生结果或存储。zhezhongStage 是直接输出结果,其输入边界可以是从外部获取数据也可以是另一个 ShuffleMapStage 的输出。一个 Job 必定会有至少一个 ResultStage

Spark SQL

SparkSQL 在 Hive 兼容层面仅依赖 HiveQL 解析、Hive 元数据也就是说,从 HQL 被解析成抽象语法树(AST) 起,就全部由 SparkSQL 接管了。SparkSQL 执行计划生成和优化都由 Catalyst(函数式关系查询优化框架)负责

SparkSQL 增加了 SchemaRDD(即带有 Schema 信息的 RDD) 使用户可以在 SparkSQL 中执行 SQL 语句

备注:SchemaRDD 在后来的 SparkSQL 版本中演化为 DataFrame

Spark 部署和应用

Spark 三种部署方式

  • Standalone:自带的资源管理框架。类似 MapReduce1.0,slot 为资源分配单位,但是不进行 map slot 和 reduce slot 切分
  • Spark on Mesos:Spark 和 Mesos 相互支持比较充分
  • Spark on YARN

统一部署

不同计算框架统一运行在 YARN 中的优势:

  • 计算资源按需伸缩
  • 不用付在应用混搭、集群利用率高
  • 共享底层存储,避免数据库跨集群迁移

Spark 编程实践

ActionAPI TransformationAPI