第 1 章 Spark 数据分析导论

第 1 章 Spark 数据分析导论

本章会从宏观角度介绍 Spark 到底是什么。如果你已经对 Spark 和相关组件有一定了解,你可以选择直接从第 2 章开始读。

1.1 Spark是什么

Spark 是一个用来实现快速通用的集群计算的平台。

在速度方面,Spark 扩展了广泛使用的 MapReduce 计算模型,而且高效地支持更多计算模式,包括交互式查询和流处理。在处理大规模数据集时,速度是非常重要的。速度快就意味着我们可以进行交互式的数据操作,否则我们每次操作就需要等待数分钟甚至数小时。Spark 的一个主要特点就是能够在内存中进行计算,因而更快。不过即使是必须在磁盘上进行的复杂计算,Spark 依然比 MapReduce 更加高效。

总的来说,Spark 适用于各种各样原先需要多种不同的分布式平台的场景,包括批处理、迭代算法、交互式查询、流处理。通过在一个统一的框架下支持这些不同的计算,Spark 使我们可以简单而低耗地把各种处理流程整合在一起。而这样的组合,在实际的数据分析过程中是很有意义的。不仅如此,Spark 的这种特性还大大减轻了原先需要对各种平台分别管理的负担。

Spark 所提供的接口非常丰富。除了提供基于 Python、Java、Scala 和 SQL 的简单易用的 API 以及内建的丰富的程序库以外,Spark 还能和其他大数据工具密切配合使用。例如,Spark 可以运行在 Hadoop 集群上,访问包括 Cassandra 在内的任意 Hadoop 数据源。

1.2 一个大一统的软件栈

Spark 项目包含多个紧密集成的组件。Spark 的核心是一个对由很多计算任务组成的、运行在多个工作机器或者是一个计算集群上的应用进行调度、分发以及监控的计算引擎。由于 Spark 的核心引擎有着速度快和通用的特点,因此 Spark 还支持为各种不同应用场景专门设计的高级组件,比如 SQL 和机器学习等。这些组件关系密切并且可以相互调用,这样你就可以像在平常软件项目中使用程序库那样,组合使用这些的组件。

各组件间密切结合的设计原理有这样几个优点。首先,软件栈中所有的程序库和高级组件都可以从下层的改进中获益。比如,当 Spark 的核心引擎新引入了一个优化时,SQL 和机器学习程序库也都能自动获得性能提升。其次,运行整个软件栈的代价变小了。不需要运行 5 到 10 套独立的软件系统了,一个机构只需要运行一套软件系统即可。这些代价包括系统的部署、维护、测试、支持等。这也意味着 Spark 软件栈中每增加一个新的组件,使用 Spark 的机构都能马上试用新加入的组件。这就把原先尝试一种新的数据分析系统所需要的下载、部署并学习一个新的软件项目的代价简化成了只需要升级 Spark。

最后,密切结合的原理的一大优点就是,我们能够构建出无缝整合不同处理模型的应用。例如,利用 Spark,你可以在一个应用中实现将数据流中的数据使用机器学习算法进行实时分类。与此同时,数据分析师也可以通过 SQL 实时查询结果数据,比如将数据与非结构化的日志文件进行连接操作。不仅如此,有经验的数据工程师和数据科学家还可以通过 Python shell 来访问这些数据,进行即时分析。其他人也可以通过独立的批处理应用访问这些数据。IT 团队始终只需要维护一套系统即可。

Spark 的各个组件如图 1-1 所示,下面来依次简要介绍它们。

图 1-1:Spark 软件栈

1.2.1 Spark Core

Spark Core 实现了 Spark 的基本功能,包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core 中还包含了对弹性分布式数据集(resilient distributed dataset,简称 RDD)的 API 定义。RDD 表示分布在多个计算节点上可以并行操作的元素集合,是 Spark 主要的编程抽象。Spark Core 提供了创建和操作这些集合的多个 API。

1.2.2 Spark SQL

Spark SQL 是 Spark 用来操作结构化数据的程序包。通过 Spark SQL,我们可以使用 SQL 或者 Apache Hive 版本的 SQL 方言(HQL)来查询数据。Spark SQL 支持多种数据源,比如 Hive 表、Parquet 以及 JSON 等。除了为 Spark 提供了一个 SQL 接口,Spark SQL 还支持开发者将 SQL 和传统的 RDD 编程的数据操作方式相结合,不论是使用 Python、Java 还是 Scala,开发者都可以在单个的应用中同时使用 SQL 和复杂的数据分析。通过与 Spark 所提供的丰富的计算环境进行如此紧密的结合,Spark SQL 得以从其他开源数据仓库工具中脱颖而出。Spark SQL 是在 Spark 1.0 中被引入的。

在 Spark SQL 之前,加州大学伯克利分校曾经尝试修改 Apache Hive 以使其运行在 Spark 上,当时的项目叫作 Shark。现在,由于 Spark SQL 与 Spark 引擎和 API 的结合更紧密,Shark 已经被 Spark SQL 所取代。

1.2.3 Spark Streaming

Spark Streaming 是 Spark 提供的对实时数据进行流式计算的组件。比如生产环境中的网页服务器日志,或是网络服务中用户提交的状态更新组成的消息队列,都是数据流。Spark Streaming 提供了用来操作数据流的 API,并且与 Spark Core 中的 RDD API 高度对应。这样一来,程序员编写应用时的学习门槛就得以降低,不论是操作内存或硬盘中的数据,还是操作实时数据流,程序员都更能应对自如。从底层设计来看,Spark Streaming 支持与 Spark Core 同级别的容错性、吞吐量以及可伸缩性。

1.2.4 MLlib

Spark 中还包含一个提供常见的机器学习(ML)功能的程序库,叫作 MLlib。MLlib 提供了很多种机器学习算法,包括分类、回归、聚类、协同过滤等,还提供了模型评估、数据导入等额外的支持功能。MLlib 还提供了一些更底层的机器学习原语,包括一个通用的梯度下降优化算法。所有这些方法都被设计为可以在集群上轻松伸缩的架构。

1.2.5 GraphX

GraphX 是用来操作图(比如社交网络的朋友关系图)的程序库,可以进行并行的图计算。与 Spark Streaming 和 Spark SQL 类似,GraphX 也扩展了 Spark 的 RDD API,能用来创建一个顶点和边都包含任意属性的有向图。GraphX 还支持针对图的各种操作(比如进行图分割的 subgraph 和操作所有顶点的 mapVertices),以及一些常用图算法(比如 PageRank 和三角计数)。

1.2.6 集群管理器

就底层而言,Spark 设计为可以高效地在一个计算节点到数千个计算节点之间伸缩计算。为了实现这样的要求,同时获得最大灵活性,Spark 支持在各种集群管理器(cluster manager)上运行,包括 Hadoop YARN、Apache Mesos,以及 Spark 自带的一个简易调度器,叫作独立调度器。如果要在没有预装任何集群管理器的机器上安装 Spark,那么 Spark 自带的独立调度器可以让你轻松入门;而如果已经有了一个装有 Hadoop YARN 或 Mesos 的集群,通过 Spark 对这些集群管理器的支持,你的应用也同样能运行在这些集群上。第 7 章会详细探讨这些不同的选项以及如何选择合适的集群管理器。

1.3 Spark的用户和用途

Spark 是一个用于集群计算的通用计算框架,因此被用于各种各样的应用程序。在前言中我们提到了本书的两大目标读者人群:数据科学家和工程师。仔细分析这两个群体以及他们使用 Spark 的方式,我们不难发现这两个群体使用 Spark 的典型用例并不一致,不过我们可以把这些用例大致分为两类——数据科学应用数据处理应用。

当然,这种领域和使用模式的划分是比较模糊的。很多人也兼有数据科学家和工程师的能力,有的时候扮演数据科学家的角色进行研究,然后摇身一变成为工程师,熟练地编写复杂的数据处理程序。不管怎样,分开看这两大群体和相应的用例是很有意义的。

1.3.1 数据科学任务

数据科学是过去几年里出现的新学科,关注的是数据分析领域。尽管没有标准的定义,但我们认为数据科学家(data scientist)就是主要负责分析数据并建模的人。数据科学家有可能具备 SQL、统计、预测建模(机器学习)等方面的经验,以及一定的使用 Python、Matlab 或 R 语言进行编程的能力。将数据转换为更方便分析和观察的格式,通常被称为数据转换(data wrangling),数据科学家也对这一过程中的必要技术有所了解。

数据科学家使用他们的技能来分析数据,以回答问题或发现一些潜在规律。他们的工作流经常会用到即时分析,所以他们可以使用交互式 shell 替代复杂应用的构建,这样可以在最短时间内得到查询语句和一些简单代码的运行结果。Spark 的速度以及简单的 API 都能在这种场景里大放光彩,而 Spark 内建的程序库的支持也使得很多算法能够即刻使用。

Spark 通过一系列组件支持各种数据科学任务。Spark shell 通过提供 Python 和 Scala 的接口,使我们方便地进行交互式数据分析。Spark SQL 也提供一个独立的 SQL shell,我们可以在这个 shell 中使用 SQL 探索数据,也可以通过标准的 Spark 程序或者 Spark shell 来进行 SQL 查询。机器学习和数据分析则通过 MLlib 程序库提供支持。另外,Spark 还能支持调用 R 或者 Matlab 写成的外部程序。数据科学家在使用 R 或 Pandas 等传统数据分析工具时所能处理的数据集受限于单机,而有了 Spark,就能处理更大数据规模的问题。

在初始的探索阶段之后,数据科学家的工作需要被应用到实际中。具体问题包括扩展应用的功能、提高应用的稳定性,并针对生产环境进行配置,使之成为业务应用的一部分。例如,在数据科学家完成初始的调研之后,我们可能最终会得到一个生产环境中的推荐系统,可以整合在网页应用中,为用户提供产品推荐。一般来说,将数据科学家的工作转化为实际生产中的应用的工作是由另外的工程师或者工程师团队完成的,而不是那些数据科学家。

1.3.2 数据处理应用

Spark 的另一个主要用例是针对工程师的。在这里,我们把工程师定义为使用 Spark 开发生产环境中的数据处理应用的软件开发者。这些开发者一般有基本的软件工程概念,比如封装、接口设计以及面向对象的编程思想,他们通常有计算机专业的背景,并且能使用工程技术来设计和搭建软件系统,以实现业务用例。

对工程师来说,Spark 为开发用于集群并行执行的程序提供了一条捷径。通过封装,Spark 不需要开发者关注如何在分布式系统上编程这样的复杂问题,也无需过多关注网络通信和程序容错性。Spark 已经为工程师提供了足够的接口来快速实现常见的任务,以及对应用进行监视、审查和性能调优。其 API 模块化的特性(基于传递分布式的对象集)使得利用程序库进行开发以及本地测试大大简化。

Spark 用户之所以选择 Spark 来开发他们的数据处理应用,正是因为 Spark 提供了丰富的功能,容易学习和使用,并且成熟稳定。

1.4 Spark简史

Spark 是由一个强大而活跃的开源社区开发和维护的,社区中的开发者们来自许许多多不同的机构。如果你或者你所在的机构是第一次尝试使用 Spark,也许你会对 Spark 这个项目的历史感兴趣。Spark 是于 2009 年作为一个研究项目在加州大学伯克利分校 RAD 实验室(AMPLab 的前身)诞生。实验室中的一些研究人员曾经用过 Hadoop MapReduce。他们发现 MapReduce 在迭代计算和交互计算的任务上表现得效率低下。因此,Spark 从一开始就是为交互式查询和迭代算法设计的,同时还支持内存式存储和高效的容错机制。

2009 年,关于 Spark 的研究论文在学术会议上发表,同年 Spark 项目正式诞生。其后不久,相比于 MapReduce,Spark 在某些任务上已经获得了 10 ~ 20 倍的性能提升。

Spark 最早的一部分用户来自加州伯克利分校的其他研究小组,其中比较著名的有 Mobile Millennium。作为机器学习领域的研究项目,他们利用 Spark 来监控并预测旧金山湾区的交通拥堵情况。仅仅过了短短的一段时间,许多外部机构也开始使用 Spark。如今,有超过 50 个机构将自己添加到了使用 Spark 的机构列表页面(https://cwiki.apache.org/confluence/display/SPARK/Powered+By+Spark)。在 Spark 社区如火如荼的社区活动 Spark Meetups(http://www.meetup.com/spark-users/)和 Spark 峰会(http://spark-summit.org/)中,许多机构也向大家积极分享他们特有的 Spark 应用场景。除了加州大学伯克利分校,对 Spark 作出贡献的主要机构还有 Databricks、雅虎以及英特尔。

2011 年,AMPLab 开始基于 Spark 开发更高层的组件,比如 Shark(Spark 上的 Hive)1 和 Spark Streaming。这些组件和其他一些组件一起被称为伯克利数据分析工具栈(BDAS,https://amplab.cs.berkeley.edu/software/)。

1Shark 已经被 Spark SQL 所取代。

Spark 最早在 2010 年 3 月开源,并且在 2013 年 6 月交给了 Apache 基金会,现在已经成了 Apache 开源基金会的顶级项目。

1.5 Spark的版本和发布

自其出现以来,Spark 就一直是一个非常活跃的项目,Spark 社区也一直保持着非常繁荣的态势。随着版本号的不断更迭,Spark 的贡献者也与日俱增。Spark 1.0 吸引了 100 多个开源程序员参与开发。尽管项目活跃度在飞速地提升,Spark 社区依然保持着常规的发布新版本的节奏。2014 年 5 月,Spark 1.0 正式发布,而本书则主要关注 Spark 1.1.0 以及后续的版本。不过,大多数概念在老版本的 Spark 中依然适用,而大多数示例也能运行在老版本的 Spark 上。

1.6 Spark的存储层次

Spark 不仅可以将任何 Hadoop 分布式文件系统(HDFS)上的文件读取为分布式数据集,也可以支持其他支持 Hadoop 接口的系统,比如本地文件、亚马逊 S3、Cassandra、Hive、HBase 等。我们需要弄清楚的是,Hadoop 并非 Spark 的必要条件,Spark 支持任何实现了 Hadoop 接口的存储系统。Spark 支持的 Hadoop 输入格式包括文本文件、SequenceFile、Avro、Parquet 等。我们会在第 5 章讨论读取和存储时详细介绍如何与这些数据源进行交互。

目录