[大数据]spark(介绍)

2,506 阅读14分钟

关键词总结

开源, 分布式, 基于内存计算, 大数据处理框架(其中由很多组件构成, 比如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 的核心优势源于其独特的设计理念:

  1. 极快的速度:

    • 内存计算: 这是 Spark 最大的杀手锏。它将计算的中间结果尽可能保存在集群节点的内存中,避免了 MapReduce 等框架需要将每个阶段的输出写入磁盘的昂贵开销。对于需要多次访问同一数据集的迭代算法(如机器学习)和交互式查询,速度提升可达 10倍到100倍
    • 先进的 DAG 执行引擎: Spark 将用户程序构建成一个有向无环图(DAG),表示任务之间的依赖关系。DAG 调度器能够进行全局优化(如流水线执行、阶段合并),并高效地将任务分发到集群节点执行。
    • 查询优化器: Spark SQL 的 Catalyst 优化器是 Spark 高性能的关键。它对 SQL 查询和 DataFrame/Dataset 操作进行复杂的逻辑和物理优化(如谓词下推、列裁剪、常量折叠、连接优化),生成最优的执行计划。
  2. 易用性:

    • 丰富的 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,方便数据探索和快速原型开发。
  3. 通用性:

    • 如前所述,一个 Spark 核心引擎支持多种工作负载,无需为批处理、流处理、机器学习等分别部署和维护不同的框架(如 MapReduce, Storm, Mahout)。
  4. 强大的生态系统:

    • 数据源: 支持从 HDFS, S3, HBase, Cassandra, Kafka, Kinesis, JDBC/ODBC 数据库、JSON, CSV, Parquet, ORC 等多种数据源读取和写入数据。
    • 集群管理器: 可以运行在独立的集群模式、Hadoop YARN、Apache Mesos、Kubernetes 上,灵活利用资源。
    • 开发者工具: 提供 Web UI 监控作业、Spark History Server 查看历史作业、丰富的配置选项。
  5. 容错性:

    • Spark 通过其 弹性分布式数据集 (RDD) 的概念实现容错。RDD 记录了数据是如何通过一系列转换(Transformation)从稳定存储(如 HDFS)或其它 RDD 派生出来的(称为 Lineage 血统)。如果一个 RDD 的分区数据丢失,Spark 可以根据 Lineage 信息重新计算该分区,而不是简单地进行数据复制。这比跨集群复制大量数据更高效。
    • DAG 调度器也能在任务失败时重新调度执行。
  6. 可扩展性:

    • 可以轻松扩展到数百甚至数千台节点,处理 PB 级的数据。其架构设计使其能够线性扩展。

4. 它由哪些组件构成?

Spark 采用主从(Master/Slave)架构,主要组件包括:

  1. Driver Program (驱动程序):

    • 运行用户编写的 main() 函数的进程。
    • 负责:
      • 将用户程序解析成多个 Job(作业)。
      • 通过 DAGScheduler 将 Job 转换为由 Stage(阶段)组成的 DAG。
      • 通过 TaskScheduler 将 Stage 分解为 Task(任务)。
      • 与 Cluster Manager 协商资源。
      • 将 Task 分发给 Executor 执行。
      • 监控 Task 执行状态,处理错误和重试。
      • 收集结果。
  2. Cluster Manager (集群管理器):

    • 负责在集群层面管理和分配资源(CPU、内存)。
    • Spark 支持多种集群管理器:
      • Standalone: Spark 内置的简单集群管理器。
      • Apache Hadoop YARN: Hadoop 生态系统的资源管理器(最常用)。
      • Apache Mesos: 通用的集群资源管理器(逐渐被 YARN/K8s 取代)。
      • Kubernetes: 容器编排平台(增长迅速)。
  3. Executor (执行器):

    • 运行在集群工作节点(Worker Node)上的进程。
    • 负责:
      • 执行 Driver 分配的具体 Task(计算任务)。
      • 将数据存储在内存(或磁盘)中(如 RDD 的分区)。
      • 将计算结果返回给 Driver 或写入外部存储。
      • 每个应用程序(Application)都有自己的一组 Executor 进程。
  4. Worker Node (工作节点):

    • 集群中运行 Executor 进程并提供计算资源的物理或虚拟机。
  5. Spark Core:

    • Spark 的底层基础引擎。
    • 提供核心功能:
      • 任务调度。
      • 内存管理。
      • 故障恢复。
      • 与存储系统交互。
      • 定义和操作 RDD (Resilient Distributed Dataset - 弹性分布式数据集) 的核心抽象。RDD 是 Spark 最基本的数据表示形式,代表一个不可变、可分区、可并行计算的元素集合。它是所有其他高级 API(如 DataFrame, Dataset)构建的基础。
  6. 高级 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 方向演进。

架构图简化示意:

[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 高效运行的核心原理主要围绕以下几个方面:

  1. 弹性分布式数据集 (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 的构建和任务的提交执行。
    • 持久化/缓存: 用户可以将频繁访问的 RDD 显式地 persist()cache() 在内存(或磁盘)中,避免后续动作重复计算它,极大提升性能。
  2. 有向无环图 (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。
    • 任务 (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)。
  3. 内存计算:

    • Spark 最核心的加速原理。它优先将计算的中间结果(RDD 的分区)保存在 Executor 进程的内存中。
    • 后续的操作如果需要用到这些中间结果,可以直接从内存中读取,避免了传统 MapReduce 需要将每个 Map 和 Reduce 阶段的输出都写入 HDFS 磁盘的 I/O 瓶颈。这对于需要多次访问同一数据集的迭代算法(机器学习)和交互式查询至关重要。
    • 内存不足时,Spark 会将数据溢出 (Spill) 到磁盘。
  4. Catalyst 优化器 (Spark SQL 核心):

    • Spark SQL 性能卓越的关键。
    • 它是一个基于规则的优化器,接收用户用 SQL 或 DataFrame/Dataset API 表达的查询。
    • 优化过程:
      1. 分析 (Analysis): 解析 SQL 或代码,构建逻辑计划 (Logical Plan),检查表和列是否存在、类型是否匹配。
      2. 逻辑优化 (Logical Optimization): 应用一系列优化规则 (Rules) 来简化或改进逻辑计划(如谓词下推、常量折叠、列裁剪、投影消除、连接重排序)。
      3. 物理规划 (Physical Planning): 将优化后的逻辑计划转换成多个可能的物理执行计划 (Physical Plans)。
      4. 代价模型与选择 (Cost Model & Selection): 基于代价模型(统计信息、规则)选择最优的物理执行计划。
      5. 代码生成 (Code Generation): 将选定的物理计划编译成高效的 Java 字节码(通过 Janino 或 JIT)在 Executor 上执行。Tungsten 项目极大地改进了这部分,使用二进制格式和手写代码优化。
  5. Tungsten 执行引擎:

    • Spark 性能的另一个飞跃,专注于 CPU 和内存效率。
    • 主要优化:
      • 堆外内存管理: 使用 sun.misc.Unsafe 直接操作操作系统内存,避免 JVM GC 开销,更紧凑的数据表示。
      • 缓存感知计算: 优化算法和数据结构以利用 CPU 缓存(L1/L2/L3)。
      • 代码生成: 在运行时动态生成特定查询的优化字节码,避免虚拟函数调用等解释开销(与 Catalyst 紧密集成)。

总结 Spark 的工作原理流程:

  1. 用户编写 Spark 程序(使用 RDD、DataFrame/Dataset API 或 SQL)。
  2. 程序提交给 Driver。
  3. 当遇到一个 Action 时,Driver:
    • 根据 RDD 的血统(或 DataFrame/Dataset 的逻辑计划)构建 DAG
    • DAGScheduler 根据 Shuffle 边界将 DAG 划分为 Stage(窄依赖合并,宽依赖切分)。
    • TaskScheduler 将 Stage 拆分成 Task(每个 Stage 分区一个 Task),并通过 Cluster Manager 申请资源。
  4. Cluster Manager 在 Worker Node 上启动 Executor
  5. TaskSchedulerTask 分发到 Executor 上执行。
  6. Executor 执行 Task
    • 优先在内存中进行计算和数据存储。
    • 执行涉及 Shuffle 操作时,进行跨节点数据交换。
    • 利用 Catalyst 优化后的计划和 Tungsten 生成的高效代码。
  7. Executor 将结果返回给 Driver 或写入外部存储。
  8. 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 应用的关键。