处理大数据,很多人第一反应可能是 Hadoop MapReduce。没错,它曾经是主流。但是,想象一下,每次你要处理数据,都得先把数据从硬盘读出来,计算完,再写回硬盘。如果是一个复杂任务,需要很多步骤,这个过程就会重复很多次。这就像你每次只想从书里找一句话,却不得不把整本书从头到尾读一遍,效率很低。
Spark 的出现就是为了解决这个问题。简单说,Spark 是一个用于大规模数据处理的统一分析引擎。 它最核心的改进,就是把计算过程中的中间数据尽可能地放在内存里。 这就像你把经常要读的书放在手边的桌子上,而不是每次都回书架去找,速度自然就快很多。数据显示,基于内存的运算,Spark 能比 Hadoop MapReduce 快 100 倍以上;即使是基于硬盘的运算,也能快 10 倍以上。
Spark 的特点
除了快,Spark 还有几个让它变得流行的特点。
首先是通用性强。Spark 的设计目标就是成为一个一站式平台,在一个框架内处理各种大数据任务。 它就像一个瑞士军刀,集成了好几个工具,你可以用它来做批量数据处理 (Batch Processing)、交互式查询 (Interactive Queries)、实时流处理 (Stream Processing)、机器学习 (Machine Learning) 和图计算 (Graph Processing)。
- Spark SQL:让你可以像用传统数据库一样,通过 SQL 语句来查询大规模的结构化数据。 这对那些熟悉 SQL 但不熟悉复杂编程的数据分析师来说,非常友好。
- Spark Streaming:用于处理实时数据流。 比如,网站的用户行为日志、社交媒体上的信息流,都可以用它来做实时分析。
- MLlib:这是 Spark 的机器学习库,包含了很多常见的机器学习算法,比如分类、回归、聚类等。 它的好处是这些算法都可以在集群上分布式运行,处理海量数据。
- GraphX:这是用于图计算的库。 社交网络里的人际关系、或者地图上的路径规划,这些都可以抽象成图结构,用 GraphX 来分析。
因为这些组件都集成在一个框架里,它们可以无缝地组合使用,数据不需要在不同系统之间倒来倒去,减少了开发和维护的成本。
其次是易用性。Spark 提供了对多种编程语言的支持,包括 Java、Scala、Python 和 R。 这意味着不同背景的开发者,无论是 Java 工程师、数据科学家还是统计分析师,都可以用自己熟悉的语言来开发 Spark 应用。 而且它提供了超过 80 种高级算法或操作,让代码写起来更简单直接。
最后是容错性。分布式系统最怕的就是某个计算节点出故障。Spark 通过一种叫做“弹性分布式数据集”(Resilient Distributed Dataset, RDD)的东西来保证容错。 RDD 是 Spark 最基本的数据抽象,你可以把它想象成一个分布在集群中多个机器上的、不可变的数据集合。 RDD 会记录它是通过哪些步骤计算得来的。一旦某个分区的数据丢失了,Spark 就可以根据这个“血缘关系”重新计算出丢失的数据,而不需要从头开始。
Spark 的核心结构
要理解 Spark 是怎么工作的,需要了解它的基本架构,主要包括三个部分:Driver(驱动程序)、Cluster Manager(集群管理器)和 Executor(执行器)。
整个结构有点像一个项目团队。
Driver(驱动程序):这是你写的 Spark 应用的“大脑”或者说是“项目经理”。 当你提交一个应用,Driver 程序会先启动。它的主要工作是:
1. 把你的代码转换成一系列具体的任务 (Tasks)。 它会分析你的计算逻辑,生成一个叫做“有向无环图”(DAG)的执行计划。
2. 向 Cluster Manager 申请计算资源(也就是 Executor)。
3. 把这些任务分配给 Executor 去执行,并全程监控任务的进展。
Cluster Manager(集群管理器):这是集群的“资源调度中心”。 它负责管理集群里所有的计算资源。Spark 本身支持一个独立的集群管理器 (Standalone),但更常见的做法是把它运行在更专业的资源管理系统上,比如 Hadoop YARN 或者 Mesos。 Driver 程序会向它申请资源,它会根据集群的负载情况,在 Worker Node(工作节点)上分配相应的资源。
Worker Node & Executor(工作节点和执行器):Worker Node 就是集群里的物理机器,是真正干活的“员工”。 每个 Worker Node 上可以运行一个或多个 Executor 进程。
Executor 是具体执行任务的单元。 它们接到 Driver 分配的任务后,就开始进行计算。 同时,它们会把计算过程中产生的数据缓存到内存或磁盘上,以便后续的任务可以复用。 计算完成后,结果会返回给 Driver。
整个工作流程大致是这样的:
1. 你提交一个 Spark 应用。
2. Driver 程序启动,解析你的代码,生成执行计划,然后向 Cluster Manager 申请资源。
3. Cluster Manager 在 Worker Node 上启动指定数量的 Executor。
4. Executor 启动后会反向注册到 Driver 上,表示“我准备好了”。
5. Driver 把具体的计算任务分配给各个 Executor。
6. Executor 开始执行任务,并在需要时相互通信交换数据。
7. 所有任务完成后,Driver 程序结束。
核心数据抽象:从 RDD 到 DataFrame 和 Dataset
Spark 的数据抽象也在不断进化。
最开始是 RDD。它的优点是灵活,可以存放任何类型的 Java 或 Python 对象。 但缺点是 Spark 不了解 RDD 内部数据的具体结构,所以在优化计算上能力有限,性能也不是最优的。
为了解决这个问题,Spark 引入了 DataFrame。DataFrame 是一种更高级的抽象,它把数据组织成带有列名的表格形式,就像关系型数据库里的表或者 Python pandas 里的 DataFrame。 因为有了明确的结构信息 (Schema),Spark 就可以通过一个叫做 Catalyst 的优化器来对你的计算过程进行深度优化,从而大幅提升性能。 你可以直接对 DataFrame 使用类似 SQL 的语句进行操作。
但是 DataFrame 也有缺点,它在编译时不做类型检查,如果你代码里字段名写错了或者类型不对,只有在运行时才会发现错误。
于是,Spark 后来又推出了 Dataset API。 Dataset 结合了 RDD 和 DataFrame 两者的优点。它既有 DataFrame 那样的结构化数据和性能优化,又像 RDD 一样是强类型的,可以在编译阶段就检查出类型错误,这对于用 Java 或 Scala 这种静态类型语言的开发者来说非常有用。 在 Scala 和 Java 里,DataFrame 其实就是 Dataset[Row] 的一个特例。
简单来说,如果你需要对数据进行精细的底层操作,或者数据是非结构化的,可以用 RDD。 如果你的数据是结构化的,并且追求性能,用 DataFrame 是最好的选择,尤其是在 Python 或 R 环境下。 如果你用的是 Scala 或 Java,并且希望在获得高性能的同时还能保证类型安全,那么用 Dataset 是最理想的。

七点爱学
评论前必须登录!
立即登录 注册