一、概述

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark 是 UC Berkeley AMP lab(加州大学伯克利分校的 AMP 实验室)所开源的类 Hadoop MapReduce 的通用并行框架。

二、模块设计

Spark 是一个功能丰富的大数据计算平台,与所有的大型系统一样,Spark 从设计到开发,也根据功能的不同进行模块的拆分。Spark 包含很多子模块,模块按照重要程度可分为核心功能和扩展功能。核心功能是 Spark 设计理念的核心实现,也是 Spark 陆续加入新功能的基础。在核心功能之上,通过不断地将丰富的扩展功能持续集成到 Spark。

2.1. Spark Core

Spark Core 提供了 Spark 最基础与最核心的功能。

2.1.1. 基础服务设施

在 Spark 中有很多基础设施,被 Spark 中的各种组件广泛使用。这些基础设施包括 Spark 配置、通信设施、事件总线、度量系统等。

  1. 通信服务 RpcEnv

  2. 安全服务

    对于 Spark 来说,我们需要考虑的三个方面的安全问题

    1. 权限管理

      保证相应的用户不能做出超越权限的操作

      • ACL

        Spark支持基本的 ACL,通过配置不同用户的角色,能为不同的用户赋予不同的权限范围。

    2. 数据/链路加密

      数据/链路加密是 Spark 安全中最为重要的一块,它主要是为了防止匿名用户通过端口获取报文,发送malicious数据,同时也需要防止用户伪造spilled 数据(如shuffle数据)以破坏运行作业。

      • 数据加密

        在 Spark 中,往 local disk 上写的数据, 如: Shuffle数据,包括 shuffle data 和 shuffle index file。这些数据序列化后写入到 local 文件系统中。如果一个用户知道 Spark 中 shuffle 数据的命名方式和映射规律,那么就能伪造一份新的 shuffle 数据。为了防止此种情况的发生,需要对写到 disk 上的数据进行加密。

    3. 与其他安全系统交互

      在一个完整的生产环境集群中,Spark 并不是唯一的系统,通常还需要与其他的调度、存储系统进行交互,如 HDFS,YARN 等。如果其他的系统都是需要安全认证的,Spark作为其他系统的使用方,需要和其他系统安全进行交互。

  3. 序列化服务

    SerializerManager 是为各种 Spark 组件配置序列化,压缩和加密的组件,包括自动选择用于 shuffle 的 Serializer, Spark 中的数据在 Network IO 或 local disk IO 传输过程都需要序列化。

  4. 度量服务

    Spark 作为优秀的开源系统,在监控方面也有自己的一整套体系,Spark 基于 Metrics 实现了自己的度量系统。

2.1.2. 执行环境 SparkEnv

Spark 执行环境 SparkEnv 是 Spark 中的 Task 运行所必需的组件。SparkEnv 内部封装了 RPC 环境 (RpcEnv)、序列化管理器、广播管理器 (BroadcastManager)、map 任务输出跟踪器(MapoutputTracker)、存储体系、度量系统(MetricsSystem)、输出提交协调器(OutputCommitCoordinator) 等 Task 运行所需的各种组件。

  1. 存储体系
    Spark 优先考虑使用各节点的内存作为存储,当内存不足时才会考虑使用磁盘,极大地减少了磁盘 IO,提升了任务执行的效率,使得 Spark 适用于实时计算、迭代计算、流式计算等场景
  2. map 任务输出跟踪器

2.1.3. SparkContext (客户端的东西?)

用户开发的 Spark 应用程序的提交与执行都离不开 SparkContext 的支持。在正式提交应用程序之前,首先需要初始化 SparkContext。SparkContext 隐藏了网络通信、分布式部署、消息通信、存储体系、计算引擎、度量系统、文件服务、Web UI 等内容,应用程序开发者只需要使用 SparkContext 提供的 API 完成功能开发。

2.1.4. 调度系统(Cluster Manager 的东西?)

Spark 调度系统分为资源调度和任务调度两个部分,作业提交之后首先由资源调度系统为作业分配所需的计算资源,并创 Driver 和 Executor 实例;然后由任务调度系统通过解析作业的计算逻辑进一步划分 stage、创建 TaskSet 并根据调度算法将 TaskSet 分发到合适的 Executor 执行器上去运行。

2.1.5. 计算引擎 (Executor)

计算引擎负责计算分配到 Executor 任务

计算引擎

2.2. Libraries

Spark SQL 是 Spark 用来处理结构化数据的一个模块,它提供了 2 个编程抽象:DataFrame 和 DataSet, 并且作为分布式 SQL 查询引擎的作用。

Spark Streaming 是构建在 Spark 上的实时计算框架,它扩展了 Spark 处理大规模流式数据的能力。Spark Streaming 可结合批处理和交互查询,适合一些需要对历史数据和实时数据进行结合分析的应用场景。

Spark MLlib 是 Spark 提供的一个机器学习库

2.3. API

2.3.1. DataSet & DataFrame

DataFrame 是一种以 RDD 为基础的带有 Schema 元信息的分布式数据集,类似于传统数据库的二维表格。DataSet 与 DataFrame 相比,保存了类型信息,是强类型的,提供了编译时类型检查。DataSet 包含了 DataFrame 的功能。
Spark2.0 中两者统一,DateFrame 表示为 Dataset[Row],即 DataSet 的子集。DataFrame 其实就是 Dateset[Row]
如图: DataFrame 提供了详细的结构信息 Schema 列的名称和类型,类似于传统数据库的二维表格,而 DataSet[People] 不光有 Schema 信息,还有类型信息。

DataSet

2.3.2. DataStream

DataStream 是 SparkStreaming 的数据模型,基于内存处理连续的数据流,本质上就是 RDD 的序列

2.4. Deploy

Spark 部署模式目前主要有用于测试的 local 本地模式、standalone 模式以及第三方资源模式(Kubernetes、Yarn、Mesos)

2.5. 外部组件

Spark 集群和外部组件进行交互: Kafka、Hive

三、集群组件

Spark 集群组件

3.1. Client

3.2. Cluster Manager

Spark 的集群管理器,主要负责对整个集群资源的分配与管理,目前 Spark 支持 4 种 Cluster Manager

Cluster Manager 在 YARN 部署模式下为 ResourceManager,在 Standalone 部署模式下为 Master。

  1. Standalone: Spark 自带的集群管理模式
  2. Apache Mesos: Mesos 是一种通用的集群资源管理服务,用于管理 MapReduce 应用或者其他关型的应用。
  3. Hadoop YARN: YARN 是由 Hadoop 2.0 引入的集群资源管理服务。
  4. Kubernetes: Spark 2.3 以后引入了对 Kubernetes 的支持。

Cluster Manager 分配的资源属于一级分配,它将各个 Worker 上的内存、CPU 等资源分配给 Application,但是并不负责对 Executor 的资源分配。Standalone 部署模式下的 Master 会直接给 Application 分配内存、CPU及 Executor 等资源。

3.3. Worker

Worker Node 是 Spark 的工作节点。在 YARN 部署模式下为 NodeManager。 Worker 节点主要负责以下工作:

  1. 将自身内存、CPU 等资源通过注册机制告知 Cluster Manager;
  2. 创建 Executor
  3. 分配资源任务,同步资源信息、Executor 状态信息给 Cluster Manager 等。

四、运行时架构

Spark 集群运行时一般拥有单个的 Driver 和多个的 Executor,可以运行在单台机器上,也可以运行在多台机器上。 Driver 和 Executor 都是独立运行的 JVM 进程。

集群启动

4.1. Driver

客户端驱动程序,也可以理解为客户端应用程序,用于将任务程序转换为 RDD 和 DAG,并与 Cluster Manager 进行通信与调度。Driver 是 Spark Application 的主入口,负责实际代码的执行工作。Driver 在 Spark 作业执行时主要负责:

  1. 将用户程序转化为任务 (Job)
  2. Executor 之间调度任务 task
  3. 跟踪 Executor 的执行情况
  4. 通过 UI 展示查询运行情况

4.2. Executor

五、部署模式

5.1. 本地模式

Local[N] 模式,用单机的多个线程来模拟 Spark 分布式计算,直接运行在本地,便于调试,通常用来验证开发出来的应用程序逻辑上有没有问题。

其中 N 代表可以使用 N 个线程,每个线程拥有一个 core。如果不指定 N,则默认是1个线程,该线程有1个core。

  1. local 只启动一个 executor
  2. local[k] 启动 k 个 executor
  3. local[*] 启动 和 cpu 数目相同的 executor

5.2. Standalone 模式

独立模式,自带完整的服务,使用 Spark 自带的资源调度框架, 无需依赖任何其他资源管理系统, 可单独部署到一个集群中。

5.3. 第三方资源管理器

5.3.1. Spark On YARN

Spark on yarn 的支持两种模式: cluster&client
Yarn-cluster 和 Yarn-client 模式的区别其实就是 AppMaster 进程的区别
Yarn-cluster 模式下,driver 运行在 Application Master 中,它负责向 Yarn 申请资源,并监督作业的运行状况。当用户提交了作业之后,就可以关掉 Client,作业会继续在 Yarn 上运行。然而 Yarn-cluster 模式不适合运行交互类型的作业。
而 Yarn-client 模式下,AppMaster 仅仅向 Yarn 请求 executor,client 会和请求的 container 通信来调度他们工作。

  1. yarn-cluster: 适用于生产环境

    yarn-cluster
  2. yarn-client: 适用于交互、调试,希望立即看到 app 的输出

    yarn-cluster

yarn-cluster 和 yarn-client 的区别在于 yarn AppMaster,每个 yarn app 实例有一个 AppMaster 进程,是为 app 启动的第一个 container 负责从 ResourceManager 请求资源,获取到资源后,告诉 NodeManager 为其启动 container。

5.3.2. Spark On K8S

5.3.3. Spark On Mesos

Spark 运行在 Mesos 上会比运行在 YARN 上更加灵活,更加自然。目前在 Spark\ On\ Mesos 环境中,用户可选择两种调度模式运行自己的应用程序。

  1. 粗粒度模式

    应用程序的各个任务正式运行之前,需要将运行环境中需要的资源全部申请好,且运行过程中要一直占用这些资源,即使不用,最后程序运行结束后,回收这些资源。

  2. 细粒度模式

    鉴于粗粒度模式会造成大量资源浪费,Spark On Mesos 还提供了另外一种调度模式:细粒度模式,这种模式思想是按需分配,每个 executor 占用资源仅仅是自己运行所需的资源,不需要考虑将来要运行的任务

    mesos 会为每个 executor 动态分配资源,每分配一些,便可以运行一个新任务,单个 Task 运行完之后可以马上释放对应的资源。每个 Task 会汇报状态给 Mesos slave 和 Mesos Master ,便于更加细粒度管理和容错,这种调度模式类似于 MapReduce 调度模式,每个 Task 完全独立,优点是便于资源控制和隔离,但缺点也很明显,短作业运行延迟大。

六、Hadoop&Spark

6.1. 计算架构

  • Hadoop 底层使用 MapReduce 计算架构,只有 map 和 reduce 两种操作,而且在 MapReduce 过程中会重复的读写 hdfs,造成大量的磁盘 io 读写操作。
  • Spark 是基于内存的分布式计算架构,提供更加丰富的数据集操作类型,主要分成转化操作和行动操作,包括map、reduce、filter、flatmap、groupbykey等,数据分析更加快速。

6.2. 迭代式计算模型

Spark 与 Hadoop 最大的区别在于迭代式计算模型

  • 基于 MapReduce 框架的 Hadoop 主要分为 map 和 reduce 两个阶段,两个阶段完了就结束了,所以在一个 job 里面能做的处理很有限

    也就是说,一次数据过程包含从共享文件系统读取数据、进行计算、完成计算、写入计算结果到共享存储中

  • Spark 计算模型是基于内存的迭代式计算模型,可以分为 N 个阶段,根据用户编写的 RDD 算子和程序,在处理完一个阶段后可以继续往下处理很多个阶段,而不只是两个阶段。

所以 Spark 相较于 MapReduce,计算模型更加灵活,可以提供更强大的功能。

6.3. 多进程模型 vs 多线程模型

MapReduce 采用了多进程模型,而 Spark 采用了多线程模型。

  • MapReduce 的 Map Task 和 Reduce Task 是进程级别的,每次启动都需要重新申请资源,消耗了不必要的时间,而 Spark Task 则是基于线程模型的

  • Spark 则是通过复用线程池中的线程来减少启动、关闭 task 所需要的开销。

    多线程模型也有缺点,由于同节点上所有任务运行在一个进程中,因此,会出现严重的资源争用,难以细粒度控制每个任务占用资源)