关键词总结
开源, 分布式, 基于内存计算, 大数据处理框架(其中由很多组件构成, 比如spark core, spark streaming, spark mllib, spark sql, Spark GraphX, 不同的组件发挥了不同的作用)
基于内存计算, 避免了传统计算框架(比如hadoop)频繁读写磁盘, 所以速度比较快.
是对mapreduce计算引擎的替代和升级.
rdd, 弹性分布式数据集
dag, 有向无环图
1. Spark 是什么?
Apache Spark 是一个开源的、分布式、内存计算的大数据处理框架。它的核心目标是提供一个快速、通用、易用的平台,用于处理海量数据集(从GB到PB甚至EB级别)。
简单来说,Spark 就像是给数据安上了火箭引擎。它通过将数据和计算任务分散到多台计算机(集群)上并行处理,并且聪明地利用内存(RAM)来存储中间结果,避免了传统框架(如Hadoop MapReduce)频繁读写磁盘的瓶颈,从而实现了比前辈快几个数量级的处理速度。
2. 它是干什么的?(主要用途)
Spark 设计之初就是为了解决 Hadoop MapReduce 在迭代计算(如机器学习)和交互式查询(如数据分析)方面的性能瓶颈。它的主要应用场景包括:
- 大规模数据处理/批处理: 处理存储在 HDFS、S3、HBase、Cassandra 等分布式存储系统上的海量数据。例如:日志分析、ETL(数据抽取、转换、加载)、生成报表。
- 实时流处理: 使用 Spark Streaming(或更新、更优的结构化流处理 Structured Streaming)处理来自 Kafka、Flume、Kinesis 等消息系统的实时数据流。例如:实时监控、欺诈检测、实时推荐。
- 交互式查询/分析: 通过 Spark SQL,用户可以像查询传统数据库一样(使用 SQL 或 DataFrame API)对大规模数据集进行交互式探索和分析。比传统的 Hive on MapReduce 快得多。
- 机器学习: Spark MLlib 提供了丰富的、可扩展的机器学习算法库(分类、回归、聚类、协同过滤、特征工程等),利用 Spark 的并行处理能力加速模型的训练。
- 图计算: Spark GraphX 提供了用于图结构数据(如社交网络、网页链接)处理的 API 和算法。
核心目标: 用一个统一的引擎解决多种数据处理范式(批处理、流处理、交互式分析、机器学习、图计算)的需求,简化技术栈,提高开发效率和运行性能。
3. 特点和优势
Spark 的核心优势源于其独特的设计理念:
-
极快的速度:
- 内存计算: 这是 Spark 最大的杀手锏。它将计算的中间结果尽可能保存在集群节点的内存中,避免了 MapReduce 等框架需要将每个阶段的输出写入磁盘的昂贵开销。对于需要多次访问同一数据集的迭代算法(如机器学习)和交互式查询,速度提升可达 10倍到100倍。
- 先进的 DAG 执行引擎: Spark 将用户程序构建成一个有向无环图(DAG),表示任务之间的依赖关系。DAG 调度器能够进行全局优化(如流水线执行、阶段合并),并高效地将任务分发到集群节点执行。
- 查询优化器: Spark SQL 的 Catalyst 优化器是 Spark 高性能的关键。它对 SQL 查询和 DataFrame/Dataset 操作进行复杂的逻辑和物理优化(如谓词下推、列裁剪、常量折叠、连接优化),生成最优的执行计划。
-
易用性:
- 丰富的 API: 提供多种语言的高级 API:Scala, Java, Python, R, SQL。开发者可以用熟悉的语言(尤其是 Python 和 SQL)快速编写分布式程序。
- 统一的引擎: 一套代码库和 API 即可处理批处理、流处理、机器学习、图计算和交互式查询,大大简化了开发和维护。
- 内置库: 集成了 Spark SQL(结构化数据处理)、MLlib(机器学习)、GraphX(图计算)、Spark Streaming/Structured Streaming(流处理)等库,开箱即用。
- 交互式 Shell: 提供 Scala (
spark-shell)、Python (pyspark)、R (sparkR) 的交互式 Shell,方便数据探索和快速原型开发。
-
通用性:
- 如前所述,一个 Spark 核心引擎支持多种工作负载,无需为批处理、流处理、机器学习等分别部署和维护不同的框架(如 MapReduce, Storm, Mahout)。
-
强大的生态系统:
- 数据源: 支持从 HDFS, S3, HBase, Cassandra, Kafka, Kinesis, JDBC/ODBC 数据库、JSON, CSV, Parquet, ORC 等多种数据源读取和写入数据。
- 集群管理器: 可以运行在独立的集群模式、Hadoop YARN、Apache Mesos、Kubernetes 上,灵活利用资源。
- 开发者工具: 提供 Web UI 监控作业、Spark History Server 查看历史作业、丰富的配置选项。
-
容错性:
- Spark 通过其 弹性分布式数据集 (RDD) 的概念实现容错。RDD 记录了数据是如何通过一系列转换(Transformation)从稳定存储(如 HDFS)或其它 RDD 派生出来的(称为 Lineage 血统)。如果一个 RDD 的分区数据丢失,Spark 可以根据 Lineage 信息重新计算该分区,而不是简单地进行数据复制。这比跨集群复制大量数据更高效。
- DAG 调度器也能在任务失败时重新调度执行。
-
可扩展性:
- 可以轻松扩展到数百甚至数千台节点,处理 PB 级的数据。其架构设计使其能够线性扩展。
4. 它由哪些组件构成?
Spark 采用主从(Master/Slave)架构,主要组件包括:
-
Driver Program (驱动程序):
- 运行用户编写的
main()函数的进程。 - 负责:
- 将用户程序解析成多个 Job(作业)。
- 通过 DAGScheduler 将 Job 转换为由 Stage(阶段)组成的 DAG。
- 通过 TaskScheduler 将 Stage 分解为 Task(任务)。
- 与 Cluster Manager 协商资源。
- 将 Task 分发给 Executor 执行。
- 监控 Task 执行状态,处理错误和重试。
- 收集结果。
- 运行用户编写的
-
Cluster Manager (集群管理器):
- 负责在集群层面管理和分配资源(CPU、内存)。
- Spark 支持多种集群管理器:
- Standalone: Spark 内置的简单集群管理器。
- Apache Hadoop YARN: Hadoop 生态系统的资源管理器(最常用)。
- Apache Mesos: 通用的集群资源管理器(逐渐被 YARN/K8s 取代)。
- Kubernetes: 容器编排平台(增长迅速)。
-
Executor (执行器):
- 运行在集群工作节点(Worker Node)上的进程。
- 负责:
- 执行 Driver 分配的具体 Task(计算任务)。
- 将数据存储在内存(或磁盘)中(如 RDD 的分区)。
- 将计算结果返回给 Driver 或写入外部存储。
- 每个应用程序(Application)都有自己的一组 Executor 进程。
-
Worker Node (工作节点):
- 集群中运行 Executor 进程并提供计算资源的物理或虚拟机。
-
Spark Core:
- Spark 的底层基础引擎。
- 提供核心功能:
- 任务调度。
- 内存管理。
- 故障恢复。
- 与存储系统交互。
- 定义和操作 RDD (Resilient Distributed Dataset - 弹性分布式数据集) 的核心抽象。RDD 是 Spark 最基本的数据表示形式,代表一个不可变、可分区、可并行计算的元素集合。它是所有其他高级 API(如 DataFrame, Dataset)构建的基础。
-
高级 API 和库 (建立在 Spark Core 之上):
- Spark SQL:
- 用于处理结构化数据(表格式数据)。
- 核心抽象是 DataFrame (在 Python/R 中) 和 Dataset (在 Scala/Java 中)。它们本质上是带有 Schema(模式/列信息)的分布式数据集合,提供了比 RDD 更高级、更优化的操作接口(类似 Pandas 或数据库表)。
- 提供 SQL 查询接口。
- 包含强大的 Catalyst 优化器 和 Tungsten 执行引擎(使用二进制内存格式和代码生成)来加速 SQL 和 DataFrame/Dataset 操作。
- 可以读取/写入各种结构化数据源(Hive, Parquet, JSON, JDBC 等)。
- Spark Streaming:
- 最初的微批次流处理库。
- 将实时数据流切分成小批次(如每秒),然后像处理小批量数据一样使用 Spark Core 引擎处理。
- Structured Streaming:
- 基于 Spark SQL 引擎构建的更新、更优的流处理引擎(强烈推荐使用)。
- 核心抽象是将无界的实时数据流视为一个持续追加的表(Unbounded Table)。
- 使用与批处理(Spark SQL/DataFrame)相同的 API 进行查询,引擎自动处理增量计算、状态管理和容错。
- 支持事件时间、窗口操作、端到端精确一次语义。
- MLlib:
- Spark 的机器学习库。
- 提供常见的机器学习算法(分类、回归、聚类、推荐、特征提取/转换、流水线构建)。
- 基于 DataFrame API 构建,便于特征处理和流水线操作。
- 利用 Spark 的分布式计算能力加速大规模模型训练。
- GraphX:
- 用于图并行计算的 API。
- 提供图抽象(顶点、边)和操作(如 PageRank, 连通分量)。
- 建立在 RDD 之上,但未来可能会向 DataFrame 方向演进。
- Spark SQL:
架构图简化示意:
[User Code (Scala/Python/Java/R/SQL)] -> [Driver Program]
|
| (1. 解析程序, 2. 构建 DAG, 3. 调度任务)
|
v
[Cluster Manager (YARN/Mesos/K8s/Standalone)]
|
| (资源分配)
|
+------------------+------------------+
| |
v v
[Worker Node 1] [Worker Node 2] ... [Worker Node N]
| | |
v v v
[Executor] [Executor] [Executor]
| | |
v v v
[Task] [Task] ... [Task] [Task] ... [Task] [Task] ...
| | |
v v v
[Data (HDFS/S3/...) 或 内存中的 RDD/DataFrame 分区]
5. 它的原理是什么?(核心工作原理)
Spark 高效运行的核心原理主要围绕以下几个方面:
-
弹性分布式数据集 (RDD - 基石):
- 概念: RDD 是 Spark 最基本、最底层的抽象。它是一个不可变的、分区的、可并行操作的元素集合。
- 特性:
- 弹性: 可以从失败中恢复。通过记录数据的血统 (Lineage) 信息(即它是如何从其他 RDD 或稳定存储通过一系列转换操作派生出来的),如果某个分区的数据丢失,Spark 可以重新执行血统链上的操作来重新计算该分区,而不需要昂贵的跨节点数据复制。
- 分布式: 数据被自动划分为多个分区 (Partitions),分布存储在集群不同节点的 Executor 内存(或溢出到磁盘)中。
- 数据集: 包含实际数据。
- 操作类型:
- 转换 (Transformations): 从一个 RDD 创建一个新的 RDD(如
map,filter,join,groupByKey)。转换是惰性求值 (Lazy Evaluation) 的,即 Spark 不会立即执行,而是记录下要执行的操作,直到遇到一个动作 (Action)。 - 动作 (Actions): 触发实际计算,将结果返回给 Driver 程序或写入外部存储(如
count,collect,saveAsTextFile,foreach)。动作会触发 DAG 的构建和任务的提交执行。
- 转换 (Transformations): 从一个 RDD 创建一个新的 RDD(如
- 持久化/缓存: 用户可以将频繁访问的 RDD 显式地
persist()或cache()在内存(或磁盘)中,避免后续动作重复计算它,极大提升性能。
-
有向无环图 (DAG) 与调度:
- DAG 构建: 当用户在 RDD(或 DataFrame/Dataset)上调用一个动作 (Action) 时,Spark 的 Driver 程序会:
- 根据 RDD 的依赖关系(宽依赖/窄依赖)逆向回溯,构建一个表示整个计算过程的 DAG (Directed Acyclic Graph)。
- DAG 中的节点是 RDD,边是 RDD 之间的转换操作。
- 阶段 (Stage) 划分: DAGScheduler 会将 DAG 划分为多个 Stage。划分 Stage 的关键依据是 Shuffle。
- 窄依赖: 父 RDD 的每个分区最多被子 RDD 的一个分区使用(如
map,filter)。窄依赖的操作可以在同一个 Stage 内进行流水线式(Pipelining)执行,非常高效。 - 宽依赖: 父 RDD 的一个分区被子 RDD 的多个分区使用(如
groupByKey,join非 co-partitioned 情况)。宽依赖需要 Shuffle 操作(跨节点数据混洗),它是 Stage 的边界。每个宽依赖都会产生一个新的 Stage。
- 窄依赖: 父 RDD 的每个分区最多被子 RDD 的一个分区使用(如
- 任务 (Task) 调度与执行: TaskScheduler 将每个 Stage 分解为多个 Task(每个分区对应一个 Task)。然后,它将 Task 提交给 Cluster Manager,由 Cluster Manager 分发到 Worker Node 上的 Executor 中去执行。Executor 启动线程来运行 Task。
- Shuffle: 是宽依赖操作(如 reduceByKey, join)的核心过程。Mapper Task 将其输出数据根据分区规则写入本地磁盘(或内存),然后 Reducer Task 通过网络拉取(Fetch)自己所需分区的数据。Shuffle 是分布式计算中最昂贵、最影响性能的操作之一,Spark 不断优化其实现(如 Sort-based Shuffle, Tungsten-sort)。
- DAG 构建: 当用户在 RDD(或 DataFrame/Dataset)上调用一个动作 (Action) 时,Spark 的 Driver 程序会:
-
内存计算:
- Spark 最核心的加速原理。它优先将计算的中间结果(RDD 的分区)保存在 Executor 进程的内存中。
- 后续的操作如果需要用到这些中间结果,可以直接从内存中读取,避免了传统 MapReduce 需要将每个 Map 和 Reduce 阶段的输出都写入 HDFS 磁盘的 I/O 瓶颈。这对于需要多次访问同一数据集的迭代算法(机器学习)和交互式查询至关重要。
- 内存不足时,Spark 会将数据溢出 (Spill) 到磁盘。
-
Catalyst 优化器 (Spark SQL 核心):
- Spark SQL 性能卓越的关键。
- 它是一个基于规则的优化器,接收用户用 SQL 或 DataFrame/Dataset API 表达的查询。
- 优化过程:
- 分析 (Analysis): 解析 SQL 或代码,构建逻辑计划 (Logical Plan),检查表和列是否存在、类型是否匹配。
- 逻辑优化 (Logical Optimization): 应用一系列优化规则 (Rules) 来简化或改进逻辑计划(如谓词下推、常量折叠、列裁剪、投影消除、连接重排序)。
- 物理规划 (Physical Planning): 将优化后的逻辑计划转换成多个可能的物理执行计划 (Physical Plans)。
- 代价模型与选择 (Cost Model & Selection): 基于代价模型(统计信息、规则)选择最优的物理执行计划。
- 代码生成 (Code Generation): 将选定的物理计划编译成高效的 Java 字节码(通过 Janino 或 JIT)在 Executor 上执行。Tungsten 项目极大地改进了这部分,使用二进制格式和手写代码优化。
-
Tungsten 执行引擎:
- Spark 性能的另一个飞跃,专注于 CPU 和内存效率。
- 主要优化:
- 堆外内存管理: 使用 sun.misc.Unsafe 直接操作操作系统内存,避免 JVM GC 开销,更紧凑的数据表示。
- 缓存感知计算: 优化算法和数据结构以利用 CPU 缓存(L1/L2/L3)。
- 代码生成: 在运行时动态生成特定查询的优化字节码,避免虚拟函数调用等解释开销(与 Catalyst 紧密集成)。
总结 Spark 的工作原理流程:
- 用户编写 Spark 程序(使用 RDD、DataFrame/Dataset API 或 SQL)。
- 程序提交给 Driver。
- 当遇到一个 Action 时,Driver:
- 根据 RDD 的血统(或 DataFrame/Dataset 的逻辑计划)构建 DAG。
- DAGScheduler 根据 Shuffle 边界将 DAG 划分为 Stage(窄依赖合并,宽依赖切分)。
- TaskScheduler 将 Stage 拆分成 Task(每个 Stage 分区一个 Task),并通过 Cluster Manager 申请资源。
- Cluster Manager 在 Worker Node 上启动 Executor。
- TaskScheduler 将 Task 分发到 Executor 上执行。
- Executor 执行 Task:
- 优先在内存中进行计算和数据存储。
- 执行涉及 Shuffle 操作时,进行跨节点数据交换。
- 利用 Catalyst 优化后的计划和 Tungsten 生成的高效代码。
- Executor 将结果返回给 Driver 或写入外部存储。
- Driver 收集最终结果或监控作业状态。如果 Task 失败,TaskScheduler 会在其他节点上重试;如果 Stage 失败,DAGScheduler 会重新提交该 Stage 及其后续 Stage。
总结
Apache Spark 通过其革命性的 内存计算、基于 RDD/DAG 的执行模型、强大的 Catalyst 优化器 和 Tungsten 执行引擎,实现了远超前代框架(如 Hadoop MapReduce)的性能飞跃。
它的 统一引擎 设计,结合 丰富的高级 API (SQL, DataFrame, MLlib, Structured Streaming) 和 易用性,使其成为当今大数据处理领域当之无愧的事实标准。
无论是进行海量数据的批处理、实时流分析、交互式查询,还是构建机器学习模型,Spark 都提供了高效、灵活且相对易于使用的解决方案。
理解其核心组件(Driver, Executor, Cluster Manager)和核心原理(RDD, DAG, Stage, Task, Shuffle, Catalyst, Tungsten)是有效使用和优化 Spark 应用的关键。