Spark-3.5.7文档1 - 快速开始

本教程将快速介绍如何使用Spark。我们将首先通过Spark的交互式shell(支持Python或Scala)介绍API,然后演示如何用Java、Scala和Python编写应用程序。

要跟随本指南学习,请先从Spark官网下载打包发布的Spark版本。由于我们不使用HDFS,您可以下载适用于任何Hadoop版本的安装包。

请注意,在Spark 2.0之前,Spark的主要编程接口是弹性分布式数据集(RDD)。Spark 2.0之后,RDD被数据集(Dataset)取代,Dataset像RDD一样是强类型的,但在底层进行了更丰富的优化。RDD接口仍然受支持,您可以在RDD编程指南中查看更详细的参考。但我们强烈建议您转向使用Dataset,其性能优于RDD。有关Dataset的更多信息,请参阅SQL编程指南。

使用 Spark Shell 进行交互式分析

基本操作

Spark Shell提供了一种简单的方式来学习API,同时也是进行交互式数据分析的强大工具。它支持Scala(运行在Java虚拟机上,因此可以很好地使用现有的Java库)和Python两种语言。在Spark目录中运行以下命令来启动Spark Shell:

Python 方式
shell 复制代码
./bin/pyspark

或者如果当前环境中已通过 pip 安装了 PySpark:

shell 复制代码
pyspark

Spark 的主要抽象概念是一个称为数据集(Dataset)的分布式项目集合。数据集可以从 Hadoop InputFormats(如 HDFS 文件)创建,也可以通过转换其他数据集来生成。

由于 Python 的动态特性,在 Python 中我们不需要数据集是强类型的。因此,Python 中的所有数据集都是 DatasetRow 类型,我们将其称为 DataFrame,以与 Pandas 和 R 中的数据框概念保持一致。

让我们从 Spark 源码目录中的 README 文件文本创建一个新的 DataFrame:

python 复制代码
>>> textFile = spark.read.text("README.md")

您可以直接通过对 DataFrame 调用某些操作(actions)来获取值,或者转换(transform)DataFrame 以生成新的 DataFrame。有关更多详细信息,请阅读 API 文档。

python 复制代码
>>> textFile.count()  # Number of rows in this DataFrame
126

>>> textFile.first()  # First row in this DataFrame
Row(value=u'# Apache Spark')

现在让我们将这个 DataFrame 转换为一个新的 DataFrame。我们调用 filter 方法来返回一个包含文件中部分行的子集的新 DataFrame。

python 复制代码
>>> linesWithSpark = textFile.filter(textFile.value.contains("Spark"))

当然可以!我们可以将转换(transformations)和操作(actions)串联在一起使用。例如:

python 复制代码
>>> textFile.filter(textFile.value.contains("Spark")).count()  # How many lines contain "Spark"?
15
Scala 方式
scala 复制代码
./bin/spark-shell

Spark 的主要抽象概念是一个称为数据集(Dataset)的分布式项目集合。数据集可以从 Hadoop InputFormats(如 HDFS 文件)创建,也可以通过转换其他数据集来生成。让我们从 Spark 源码目录中的 README 文件文本创建一个新的数据集:

scala 复制代码
scala> val textFile = spark.read.textFile("README.md")
textFile: org.apache.spark.sql.Dataset[String] = [value: string]

您可以直接通过对数据集(Dataset)调用某些操作(actions)来获取值,或者转换(transform)数据集以生成新的数据集。有关更多详细信息,请阅读 API 文档。

scala 复制代码
scala> textFile.count() // Number of items in this Dataset
res0: Long = 126 // May be different from yours as README.md will change over time, similar to other outputs

scala> textFile.first() // First item in this Dataset
res1: String = # Apache Spark

现在让我们将这个数据集(Dataset)转换为一个新的数据集。我们调用 filter 方法来返回一个包含文件中部分项目的子集的新数据集。

scala 复制代码
scala> val linesWithSpark = textFile.filter(line => line.contains("Spark"))
linesWithSpark: org.apache.spark.sql.Dataset[String] = [value: string]

我们可以将转换(transformations)和操作(actions)串联在一起使用:

scala 复制代码
scala> textFile.filter(line => line.contains("Spark")).count() // How many lines contain "Spark"?
res3: Long = 15

关于数据集操作的更多内容

数据集操作和转换可用于更复杂的计算。假设我们想要找到单词数量最多的那一行:

Python 方式
python 复制代码
>>> from pyspark.sql import functions as sf
>>> textFile.select(sf.size(sf.split(textFile.value, "\s+")).name("numWords")).agg(sf.max(sf.col("numWords"))).collect()
[Row(max(numWords)=15)]

首先,它将一行数据映射为一个整数值,并将其别名为 "numWords",从而创建一个新的 DataFrame。随后在该 DataFrame 上调用 agg 方法以查找最大的单词计数。select 和 agg 的参数均为 Column 类型,我们可以通过 df.colName 从 DataFrame 中获取列。此外,我们还可以导入 pyspark.sql.functions 模块,该模块提供了许多便捷函数来基于现有列构建新列。

一个常见的数据流模式是 MapReduce,正如 Hadoop 所推广的那样。Spark 可以轻松实现 MapReduce 流程:

python 复制代码
>>> wordCounts = textFile.select(sf.explode(sf.split(textFile.value, "\s+")).alias("word")).groupBy("word").count()

在此,我们使用 select 中的 explode 函数,将行数据集转换为单词数据集,然后结合 groupBy 和 count 方法,计算出文件中每个单词的计数,生成一个包含两列("word" 和 "count")的 DataFrame。为了在交互式环境中收集单词计数结果,我们可以调用 collect 方法:

python 复制代码
>>> wordCounts.collect()
[Row(word=u'online', count=1), Row(word=u'graphs', count=1), ...]
Scala 方式
scala 复制代码
scala> textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
res4: Int = 15

首先,它将一行数据映射为一个整数值,从而创建一个新的数据集。随后在该数据集上调用 reduce 方法以查找最大的单词计数。map 和 reduce 的参数均为 Scala 函数字面量(闭包),可以使用任何语言特性或 Scala/Java 库。例如,我们可以轻松调用在其他地方声明的函数。这里我们将使用 Math.max() 函数来使代码更易理解:

scala 复制代码
scala> import java.lang.Math
import java.lang.Math

scala> textFile.map(line => line.split(" ").size).reduce((a, b) => Math.max(a, b))
res5: Int = 15

一个常见的数据流模式是 MapReduce,正如 Hadoop 所推广的那样。Spark 可以轻松实现 MapReduce 流程:

scala 复制代码
scala> val wordCounts = textFile.flatMap(line => line.split(" ")).groupByKey(identity).count()
wordCounts: org.apache.spark.sql.Dataset[(String, Long)] = [value: string, count(1): bigint]

在这里,我们调用 flatMap 将行数据集转换为单词数据集,然后结合 groupByKey 和 count 方法,计算出文件中每个单词的计数,生成一个包含 (String, Long) 键值对的数据集。为了在交互式环境中收集单词计数结果,我们可以调用 collect 方法:

scala 复制代码
scala> wordCounts.collect()
res6: Array[(String, Int)] = Array((means,1), (under,2), (this,3), (Because,1), (Python,2), (agree,1), (cluster.,1), ...)

缓存

Spark 还支持将数据集拉取到集群范围内的内存缓存中。这在需要重复访问数据时非常有用,例如查询小型"热"数据集或运行像 PageRank 这样的迭代算法时。举个简单的例子,我们将标记 linesWithSpark 数据集进行缓存:

Python 方式
python 复制代码
>>> linesWithSpark.cache()

>>> linesWithSpark.count()
15

>>> linesWithSpark.count()
15

使用 Spark 来探索和缓存一个仅 100 行的文本文件可能看起来有些小题大做。但有趣之处在于,这些相同的函数可以应用于非常庞大的数据集,即使这些数据分布在数十个甚至数百个节点上。您还可以通过将 bin/pyspark 连接到集群来交互式地进行此类操作,正如 RDD 编程指南中所描述的那样。

Scala 方式
scala 复制代码
scala> linesWithSpark.cache()
res7: linesWithSpark.type = [value: string]

scala> linesWithSpark.count()
res8: Long = 15

scala> linesWithSpark.count()
res9: Long = 15

使用 Spark 来探索和缓存一个仅 100 行的文本文件可能看起来有些小题大做。但有趣之处在于,这些相同的函数可以应用于非常庞大的数据集,即使这些数据分布在数十个甚至数百个节点上。您还可以通过将 bin/spark-shell 连接到集群来交互式地进行此类操作,正如 RDD 编程指南中所描述的那样。

独立应用程序

假设我们希望使用 Spark API 编写一个独立应用程序。我们将通过 Scala(使用 sbt)、Java(使用 Maven)和 Python(使用 pip)分别演示一个简单的应用示例。

Python 方式

现在我们将展示如何使用 Python API(PySpark)编写应用程序。

如果您正在构建打包的 PySpark 应用程序或库,可以将其添加到 setup.py 文件中,具体如下:

python 复制代码
    install_requires=[
        'pyspark==3.5.7'
    ]

例如,我们将创建一个简单的 Spark 应用程序:SimpleApp.py:

python 复制代码
"""SimpleApp.py"""
from pyspark.sql import SparkSession

logFile = "YOUR_SPARK_HOME/README.md"  # Should be some file on your system
spark = SparkSession.builder.appName("SimpleApp").getOrCreate()
logData = spark.read.text(logFile).cache()

numAs = logData.filter(logData.value.contains('a')).count()
numBs = logData.filter(logData.value.contains('b')).count()

print("Lines with a: %i, lines with b: %i" % (numAs, numBs))

spark.stop()

该程序仅统计文本文件中包含字母 "a" 的行数和包含字母 "b" 的行数。请注意,您需要将 YOUR_SPARK_HOME 替换为 Spark 的实际安装路径。与 Scala 和 Java 示例类似,这里我们使用 SparkSession 来创建数据集。对于需要使用自定义类或第三方库的应用程序,我们还可以通过 --py-files 参数将代码依赖项打包成 .zip 文件后提交给 spark-submit(具体细节可参考 spark-submit --help 命令)。由于 SimpleApp 非常简单,我们无需指定任何代码依赖项。

我们可以使用 bin/spark-submit 脚本来运行这个应用程序:

python 复制代码
# Use spark-submit to run your application
$ YOUR_SPARK_HOME/bin/spark-submit \
  --master local[4] \
  SimpleApp.py
...
Lines with a: 46, Lines with b: 23

如果您已在环境中通过 pip 安装了 PySpark(例如使用 pip install pyspark),则可以选择使用常规的 Python 解释器运行应用程序,或根据需要直接使用提供的 "spark-submit" 命令。

python 复制代码
# Use the Python interpreter to run your application
$ python SimpleApp.py
...
Lines with a: 46, Lines with b: 23

其他依赖管理工具(如 Conda 和 pip)也可用于管理自定义类或第三方库。另请参阅 Python 包管理 相关文档。

Scala 方式

我们将用 Scala 创建一个非常简单的 Spark 应用程序------事实上它简单到直接命名为 SimpleApp.scala:

scala 复制代码
/* SimpleApp.scala */
import org.apache.spark.sql.SparkSession

object SimpleApp {
  def main(args: Array[String]): Unit = {
    val logFile = "YOUR_SPARK_HOME/README.md" // Should be some file on your system
    val spark = SparkSession.builder.appName("Simple Application").getOrCreate()
    val logData = spark.read.textFile(logFile).cache()
    val numAs = logData.filter(line => line.contains("a")).count()
    val numBs = logData.filter(line => line.contains("b")).count()
    println(s"Lines with a: $numAs, Lines with b: $numBs")
    spark.stop()
  }
}

请注意,应用程序应定义一个 main() 方法,而不是继承 scala.App 类。继承 scala.App 的子类可能无法正常工作。

该程序仅统计 Spark README 文件中包含字母 'a' 的行数和包含字母 'b' 的行数。请注意,您需要将 YOUR_SPARK_HOME 替换为 Spark 的实际安装路径。与之前使用 Spark shell 的示例(它会自行初始化 SparkSession)不同,这里我们将 SparkSession 的初始化作为程序的一部分。

我们通过调用 SparkSession.builder 来构建 SparkSession,然后设置应用程序名称,最后调用 getOrCreate 来获取 SparkSession 实例。

由于我们的应用程序依赖于 Spark API,因此还需要包含一个 sbt 配置文件 build.sbt,其中需声明 Spark 为依赖项。该文件还需添加 Spark 所依赖的代码库:

scala 复制代码
name := "Simple Project"

version := "1.0"

scalaVersion := "2.12.18"

libraryDependencies += "org.apache.spark" %% "spark-sql" % "3.5.7"

为了让 sbt 能够正确工作,我们需要按照典型的目录结构来布局 SimpleApp.scala 和 build.sbt 文件。完成目录结构配置后,我们就可以创建一个包含应用程序代码的 JAR 包,然后使用 spark-submit 脚本来运行程序。

scala 复制代码
# Your directory layout should look like this
$ find .
.
./build.sbt
./src
./src/main
./src/main/scala
./src/main/scala/SimpleApp.scala

# Package a jar containing your application
$ sbt package
...
[info] Packaging {..}/{..}/target/scala-2.12/simple-project_2.12-1.0.jar

# Use spark-submit to run your application
$ YOUR_SPARK_HOME/bin/spark-submit \
  --class "SimpleApp" \
  --master local[4] \
  target/scala-2.12/simple-project_2.12-1.0.jar
...
Lines with a: 46, Lines with b: 23

其他依赖管理工具(如 Conda 和 pip)也可用于管理自定义类或第三方库。另请参阅 Python 包管理 相关文档。

Java 方式

此示例将使用 Maven 编译应用程序 JAR 包,但任何类似的构建系统都可以使用。

我们将创建一个非常简单的 Spark 应用程序 SimpleApp.java:

java 复制代码
/* SimpleApp.java */
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.Dataset;

public class SimpleApp {
  public static void main(String[] args) {
    String logFile = "YOUR_SPARK_HOME/README.md"; // Should be some file on your system
    SparkSession spark = SparkSession.builder().appName("Simple Application").getOrCreate();
    Dataset<String> logData = spark.read().textFile(logFile).cache();

    long numAs = logData.filter(s -> s.contains("a")).count();
    long numBs = logData.filter(s -> s.contains("b")).count();

    System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs);

    spark.stop();
  }
}

该程序仅统计 Spark README 文件中包含字母 'a' 的行数和包含字母 'b' 的行数。请注意,您需要将 YOUR_SPARK_HOME 替换为 Spark 的实际安装路径。与之前使用 Spark shell 的示例(它会自行初始化 SparkSession)不同,这里我们将 SparkSession 的初始化作为程序的一部分。

为了构建程序,我们还需要编写一个 Maven pom.xml 文件,其中需声明 Spark 为依赖项。请注意,Spark 构件都带有 Scala 版本标签。

xml 复制代码
<project>
  <groupId>edu.berkeley</groupId>
  <artifactId>simple-project</artifactId>
  <modelVersion>4.0.0</modelVersion>
  <name>Simple Project</name>
  <packaging>jar</packaging>
  <version>1.0</version>
  <dependencies>
    <dependency> <!-- Spark dependency -->
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.12</artifactId>
      <version>3.5.7</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

我们按照标准的 Maven 目录结构来布局这些文件:

shell 复制代码
$ find .
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/SimpleApp.java

现在,我们可以使用 Maven 打包应用程序,并通过 ./bin/spark-submit 来执行它。

shell 复制代码
# Package a JAR containing your application
$ mvn package
...
[INFO] Building jar: {..}/{..}/target/simple-project-1.0.jar

# Use spark-submit to run your application
$ YOUR_SPARK_HOME/bin/spark-submit \
  --class "SimpleApp" \
  --master local[4] \
  target/simple-project-1.0.jar
...
Lines with a: 46, Lines with b: 23

其他依赖管理工具(如 Conda 和 pip)也可用于管理自定义类或第三方库。另请参阅 Python 包管理相关文档。

下一步学习方向

恭喜您成功运行第一个 Spark 应用程序!

  • 若需深入了解 API,请从《RDD 编程指南》和《SQL 编程指南》开始,或查看"编程指南"菜单中的其他组件文档。

  • 如需在集群上运行应用程序,请参阅《部署指南》。

  • 此外,Spark 在 examples 目录中提供了多个示例(Scala、Java、Python、R),您可以通过以下方式运行它们:

shell 复制代码
# For Scala and Java, use run-example:
./bin/run-example SparkPi

# For Python examples, use spark-submit directly:
./bin/spark-submit examples/src/main/python/pi.py

# For R examples, use spark-submit directly:
./bin/spark-submit examples/src/main/r/dataframe.R
相关推荐
计算机毕业编程指导师9 小时前
计算机毕设选题推荐:基于Hadoop与Spark的Steam游戏数据分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·python·计算机·spark·毕业设计·steam游戏
计算机毕业编程指导师9 小时前
【计算机毕设选题推荐】基于Hadoop+Spark的白鹿抖音评论大数据分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·python·计算机·spark·毕业设计·抖音评论
计算机毕业编程指导师14 小时前
【大数据毕设选题推荐】基于Spark的WTA职业网球赛事演变与竞技格局分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·计算机·spark·毕业设计·课程设计·wta网球
计算机毕业编程指导师18 小时前
【计算机毕设选题推荐】基于Spark与Hadoop的AI就业收入区域差异分析系统 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·python·数据分析·spark·毕业设计·课程设计·ai就业收入
计算机毕业编程指导师21 小时前
【大数据毕设选题】基于Spark的电信网络诈骗话术语义特征挖掘分析系统源码 毕业设计 选题推荐 数据分析 机器学习 深度学习
大数据·hadoop·python·spark·毕业设计·课程设计·网络诈骗
计算机毕业编程指导师21 小时前
计算机大数据毕设怎么选?基于Spark的个体肥胖健康风险评估的数据分析与可视化系统带你通关 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·毕业设计·肥胖风险
IT研究室21 小时前
最新大数据毕业设计选题推荐-基于大数据的单位招聘岗位信息分析与可视化-大数据-Spark-Hadoop-Bigdata
大数据·spark·课程设计
计算机毕业编程指导师1 天前
计算机毕设答辩技巧:基于Hadoop+Django的公共交通运营数据分析与可视化系统怎么做 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·spark·毕业设计·课程设计·交通运行
计算机毕业编程指导师1 天前
【计算机毕设选题推荐】基于Hadoop+Django高频电力消耗大数据分析系统从0到1 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
hadoop·python·数据分析·spark·毕业设计·课程设计·电力
FYKJ_20101 天前
springboot手工蜀绣在线销售系统60947-计算机课程设计、毕业设计
java·spring boot·后端·python·mysql·spark·课程设计