关注公众号:登峰大数据,阅读Spark实战第二版(完整中文版),系统学习Spark3.0大数据框架!

本章涵盖了

  • 为一个典型用例构建Spark的心智模型

  • 理解相关的Java代码

  • 探索Spark应用程序的一般架构

  • 理解数据流

在本章中,您将构建Apache Spark的心智模型。心智模型是用你的思维过程和下列图表来解释事物在现实世界中是如何工作的。这一章的目标是,结合我将带你走过的思考过程,定义自己的想法。我会使用很多图表和一些代码。建立一个独一无二的Spark心智模型;这个模型将描述一个典型的场景,包括加载、处理和保存数据。还将学习这些操作的Java代码。

接下来的场景涉及到分布式加载CSV文件,执行一个简单操作,并将结果保存在PostgreSQL数据库(和Apache Derby)中。理解这个示例并不需要了解或安装PostgreSQL。如果您熟悉使用其他rdbms和Java,那么您将很容易适应这个示例。附录F提供了有关关系数据库的额外帮助(提示、安装、链接等)。

实验代码和样本数据可以在GitHub上找到:https://github.com/jgperrin/net.jgp.books.spark.ch02.

2.1建立心智模型

在本节中,您将构建Spark的心智模型。就软件而言,心智模型是一种概念图,您可以使用它来计划、预测、诊断和调试应用程序。要开始构建心智模型,您将处理一个大数据场景。在学习场景的同时,您将探索Spark的总体架构、流程和术语,并将很好地理解Spark的总体框架。

设想一下以下大数据场景:您是一个书商,在一个文件中有一个作者列表,您想对该文件执行一个操作,然后将其保存到一个数据库中。从技术上来说,这一过程如下:

  • 接收CSV文件,正如您在第1章中看到的那样。

  • 通过连接姓和名来转换数据。

  • 将结果保存在关系数据库中。

图2.1说明了您和Spark将要做的事情。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.1我在整本书中使用了特定的图标;如果你感到困惑,请查看前面的“关于本书”章节。您的应用程序(也称为驱动程序Driver)连接到Apache Spark(主程序Master),要求它加载CSV文件,进行转换,并将其保存到数据库中。在图表的左边,您可以看到时间轴(这里是t0、t1和t7);正如您可能猜到的,这些表示步骤。您的应用程序是这个流的第一个和最后一个元素。

您的应用程序或驱动程序连接到一个Spark集群。然后,应用程序告诉集群要做什么:应用程序驱动集群。在这个场景中,主程序首先加载一个CSV文件,最后保存到数据库中。

例子的运行环境

对于实验#100,我最初在macOS v10.13.2和Java 8上使用Spark v2.4.0、PostgreSQL v10.1和PostgreSQL JDBC驱动程序v42.1.4。实验#110使用Apache Derby v10.14.2.0作为后端。代码基本上是相同的,所以如果您不想(或不能)安装PostgreSQL,请遵循实验#110。

2.2 使用Java代码构建心智模型

在深入研究构建心智模型的每个步骤之前,让我们从整体上分析应用程序。

图2.2是该过程的基本表示:Spark读取一个CSV文件;将姓、逗号和名连接起来;然后将整个数据集保存到数据库中。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.2 一个简单的过程,包含三个步骤:读取CSV文件,执行一个简单的连接操作,并将结果数据保存在数据库中

当您运行此应用程序时,您将得到一条简单的流程完成消息。图2.3展示了该过程的结果。ch02表有三列——fname、lname和您想要的新列name。如果您需要数据库方面的帮助,请参阅附录F。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.3 在PostgreSQL中,CSV文件中的数据以及附加的列。这个插图使用SQLPro,但是您可以使用与数据库打包的标准工具(pgAdmin版本3或4)。

清单2.1是完整的应用程序。我尽量完整地展示代码,包括import语句,以防止您使用错误的包或使用类似名称的不赞成使用的类。此代码可以从GitHub下载:https://github.com/jgperrin/net.jgp.books.spark.ch02。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

您需要PostgreSQL JDBC驱动程序放到代码运行环境中。因此,您的pom.xml文件应该包含以下清单中的依赖项。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

由于pomm .xml是与一个章节的所有实验室共享的,并且由于实验#110使用Apache Derby而不是PostgreSQL,所以存储库(在GitHub中)中的pomm .xml也包含了对Derby的依赖关系。

2.3 深入应用程序

您已经看到了一个简单的用例,Spark从CSV文件中接入数据,执行一个简单的操作,然后将结果存储在数据库中。在本节中,您将了解幕后实际发生了什么。

首先,您将更仔细地查看第一个操作:到master的连接。在这一非功能性步骤之后,让我们了解一下数据的接入、转换,最后是在RDBMS中发布数据。

2.3.1 连接到master

对于每个Spark应用程序,第一个操作是连接到Spark master(主程序)并获得一个Spark会话(session)。这是你每次都要做的操作。清单2.3中的代码片段和图2.4展示了这一点。

在此上下文中,您将以本地模式连接到Spark。在第5章中,你会发现连接和使用Spark的三种方法。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

方法链编程使JAVA更加紧凑

近年来,越来越多的Java api使用了方法链,比如SparkSession.builder(). appname(…).master(…). getorcreate()。在此之前,您可能看到创建了更多的中间对象,有点像这样:

Object1 o1 = new Object1();
Object2 o2 = o1.getObject2();
o2.set("something");

Spark的API使用了大量的方法链。方法链使代码更紧凑、更可读。但是一个主要的缺点是调试:比如出现一个空指针异常(NPE),您将花费更多的时间调试它。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.4 应用程序(或驱动程序)连接到主程序并获得一个Spark会话。箭头表示序列流:在t0时启动应用程序,在t1时获得Spark会话。

本章中的所有插图都代表了一个时间轴。在t0处启动应用程序(main()函数),在t1处获得会话。

这第一步总是连接到一个master。现在可以要求Spark加载CSV文件。

本地模式不是集群模式,但它学习起来更容易

为了让您能够在不设置完整集群的情况下运行本章中的示例,我指定了master的local值,在本地模式下运行Spark。如果您有一个集群,您应该给出这个集群的地址。在第5章和第6章中了解更多关于集群的知识。

为了构建您的心智模型,您将假设您有一个集群而不是本地模式。

2.3.2 加载CSV文件

加载、接入和读取是您现在将要做的事情的同义词:请求Spark加载包含在CSV文件中的数据。Spark可以通过集群的各个节点分布式接入。现在是让Spark加载文件的时候了,对吗? 您已经学了本章几页内容了,学习了新的概念,所以现在是Spark为您做一些事情的时候了。

但是正如你所想象的那样,和所有优秀的大师一样,Spark做的并不多。Spark依靠的是slaves或workers。您将在Spark文档中找到这两个术语;尽管我是法国人,而且天生优柔寡断,但我还是会使用worker这个称呼。

在我们的场景中(如图2.5所示),您有三个worker。分布式接入是指你要让我们的三个worker同时接入。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.5 master知道它的worker。这里有三个worker。这是一种逻辑表示:任何worker都可以与主服务器在同一个物理节点上。每个worker都有内存(当然!),它将通过分区使用这些内存。

在t2中,主程序告诉worker加载文件,如清单2.4中所示。您可能想知道,“如果您有三个worker,那么哪个正在加载文件?”或者“如果它们同时加载,它们怎么知道从哪里开始和结束?” Spark将以分布式的方式接收CSV文件。文件必须在共享驱动器、分布式文件系统(如第18章中的HDFS)上,或者通过共享文件系统机制(如Dropbox、Box、Nextcloud或ownCloud)来共享。在这个上下文中,分区是worker内存中的一个专用区域。

//代码清单2.4
Dataset<Row> df = spark.read()
.format("csv")
.option("header", "true")
.load("data/authors.csv");

让我们看一下CSV文件(参见清单2.5)。它是一个包含两列的简单文件:lname表示姓,fname表示名。文件的第一行是一个文件头部。该文件还包含6行内容,在我们的dataframe中这将变成6行数据。

//代码清单2.5
lname,fname
Pascal,Blaise
Voltaire,François
Perrin,Jean-Georges
Maréchal,Pierre Sylvain
Karau,Holden
Zaharia,Matei

这些worker将创建任务(task)来读取文件。每个worker都可以访问节点的内存,并为任务分配一个内存分区,如图2.6所示。

在t4时,每个任务将继续读取CSV文件的一部分,如图2.7所示。当任务读取了文件数据的行内容时,将它们存储在一个专用分区中。

图2.7显示了在接入数据过程中从CSV文件复制到分区的记录,在R > P (record to partition)框中。内存框显示在哪个分区中有哪些记录。在这个示例中,包含Blaise Pascal的记录1位于第一个worker的第一个分区中。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.6 基于可用资源创建任务。worker可以创建多个任务,并为每个任务分配一个内存分区。实体任务正在运行(它们也有一个点),这与非工作任务(例如,来自另一个应用程序)形成对比,非工作任务是中空的,有一个三角形。

Spark实战第二版(涵盖Spark3.0)--第二章 架构和流程

图2.7 当数据接入发生时,每个任务将记录加载到自己的内存分区,如R > P (Record to partition)框所示。分区框包含接入完成后的记录。

为什么要关心分区及其位置?

阅读本章完整版内容,请移步公众号: 登峰大数据。

 

相关文章:

  • 2021-07-25
  • 2021-04-26
  • 2021-11-23
  • 2022-02-24
  • 2021-08-18
  • 2021-09-13
  • 2021-04-21
  • 2021-12-11
猜你喜欢
  • 2021-09-17
  • 2021-10-02
  • 2021-05-02
  • 2021-07-21
  • 2022-01-03
  • 2022-01-02
  • 2021-06-10
相关资源
相似解决方案