2. 开发环境搭建:本地模式安装、Spark-Shell初体验、第一个WordCount程序

说实话,很多初学者一上来就搞集群,结果环境配了三天,连个 Hello World 都没跑起来。我个人习惯是:先本地跑通,再上集群。本地模式虽然简单,但能让你快速理解 Spark 的核心概念。今天我们就从零开始,把环境搭好,再写个 WordCount 练练手。

2.1 本地模式安装

本地模式说白了就是 Spark 不需要集群,直接在单机上跑。它把所有进程都塞进一个 JVM 里,适合开发和调试。我在项目中经常用它来快速验证逻辑,等确认没问题了再丢到集群上跑。

2.1.1 前置条件

先确认你的机器上已经装好了 Java 8 或 11。Spark 3.x 对 Java 版本有要求,我建议直接用 Java 8,兼容性最好。

# 检查 Java 版本
java -version

# 输出示例(你的版本号可能不同)
# java version "1.8.0_291"

嗯,这里要注意:Spark 3.2 之后开始支持 Java 17,但我个人不建议在生产环境用太新的版本,踩坑概率大。

2.1.2 下载与解压

去 Apache Spark 官网下载预编译好的包。选的时候注意看 Hadoop 版本,如果你本地没装 Hadoop,选 "Pre-built for Apache Hadoop 3.2 and later" 就行。

# 下载 Spark 3.3.0(以这个版本为例)
wget https://archive.apache.org/dist/spark/spark-3.3.0/spark-3.3.0-bin-hadoop3.tgz

# 解压
tar -zxvf spark-3.3.0-bin-hadoop3.tgz

# 移动到常用目录
sudo mv spark-3.3.0-bin-hadoop3 /usr/local/spark

2.1.3 配置环境变量

编辑 ~/.bashrc 或 ~/.zshrc,加上下面几行:

export SPARK_HOME=/usr/local/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin

然后 source ~/.bashrc 让它生效。验证一下:

spark-shell --version

如果能看到版本信息,恭喜你,环境搭好了。

小技巧: 我习惯在 $SPARK_HOME/conf 目录下创建一个 spark-defaults.conf 文件,里面写上 spark.master local[*]。这样每次启动 Spark 应用时,默认就是本地模式,省得每次都要指定。

2.2 Spark-Shell 初体验

Spark-Shell 是 Spark 提供的交互式命令行工具。说白了,它就是一个 Scala REPL 环境,里面自动帮你创建好了 SparkContext 和 SparkSession。你想想看,不用写 main 方法,不用编译打包,直接敲代码就能跑,多爽。

2.2.1 启动 Spark-Shell

在终端里直接输入:

spark-shell

你会看到一堆日志输出,最后出现 scala> 提示符。启动时默认使用本地模式,使用 2 个线程(一个用于调度,一个用于执行)。

如果你想指定更多资源,可以这样:

spark-shell --master local[4] --executor-memory 2g

这表示用 4 个线程、每个执行器 2GB 内存。我在本地调试时一般给 2-4 个线程,再多也没意义,毕竟笔记本就那点资源。

2.2.2 第一个 Spark 操作

进入 Spark-Shell 后,试试这个:

val data = 1 to 10
val rdd = sc.parallelize(data)
rdd.collect()

你会看到输出 Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)。这里 sc 就是 SparkContext,Spark-Shell 启动时已经帮你创建好了。

核心概念: RDD(Resilient Distributed Dataset)是 Spark 中最基本的数据抽象。你可以把它理解成一个分布式的集合,支持各种转换操作(如 map、filter)和行动操作(如 collect、count)。

2.3 第一个 WordCount 程序

WordCount 是大数据领域的 "Hello World"。虽然简单,但它涵盖了 Spark 编程的核心流程:读取数据 → 转换处理 → 输出结果。我在面试新人时,经常用这个来考察对方对 Spark 基础 API 的掌握程度。

2.3.1 准备数据文件

先创建一个文本文件,里面随便写几行英文:

echo "hello world hello spark" > /tmp/words.txt
echo "spark is awesome spark is fast" >> /tmp/words.txt
echo "hello spark world" >> /tmp/words.txt

2.3.2 在 Spark-Shell 中运行 WordCount

在 Spark-Shell 中逐行输入以下代码:

// 1. 读取文件,生成 RDD
val lines = sc.textFile("/tmp/words.txt")

// 2. 将每行拆分成单词
val words = lines.flatMap(line => line.split(" "))

// 3. 将每个单词映射成 (word, 1) 键值对
val wordPairs = words.map(word => (word, 1))

// 4. 按单词分组并求和
val wordCounts = wordPairs.reduceByKey((a, b) => a + b)

// 5. 收集结果并打印
wordCounts.collect().foreach(println)

输出结果应该是:

(hello,2)
(world,2)
(spark,3)
(is,2)
(awesome,1)
(fast,1)

你看,整个过程不到 10 行代码。这就是 Spark 的魅力——简洁、高效。

2.3.3 代码逐行解析

步骤 代码 说明
1 sc.textFile(...) 读取文件,返回 RDD[String],每行一个元素
2 flatMap(...) 将每行按空格拆分,展平成一个单词列表
3 map(...) 将每个单词转为 (word, 1) 键值对
4 reduceByKey(...) 按 key 分组,对 value 求和
5 collect() 将结果从各分区收集到 Driver 端,打印输出
注意: collect() 会把所有数据拉到 Driver 端。如果数据量很大,会导致 Driver OOM。我曾经在线上环境看到有人对几十 GB 的数据用 collect(),结果 Driver 直接挂了。生产环境建议用 saveAsTextFile() 或 take(N) 来查看部分数据。

2.4 本章知识体系

下面这张图帮你梳理了本章的核心脉络:

第2章:开发环境搭建知识体系 本地模式安装 Spark-Shell 初体验 WordCount 程序 Java 环境 下载解压 环境变量 启动命令 RDD 操作 sc 上下文 数据准备 转换算子 结果收集 核心要点 • 本地模式适合开发调试,无需集群环境 • Spark-Shell 提供交互式编程体验,自动创建 SparkContext • WordCount 涵盖 RDD 核心操作:textFile → flatMap → map → reduceByKey

2.5 避坑指南

最后分享几个我踩过的坑:

  • 路径问题: sc.textFile() 默认读取 HDFS 路径。如果你在本地模式想读本地文件,一定要用 file:// 前缀,比如 sc.textFile("file:///tmp/words.txt")。我曾经忘了加这个前缀,结果一直报文件找不到,折腾了半小时才发现。
  • 日志刷屏: Spark-Shell 启动时会输出大量 INFO 日志。你可以把 $SPARK_HOME/conf/log4j.properties.template 复制为 log4j.properties,然后把 log4j.rootCategory=INFO, console 改成 log4j.rootCategory=WARN, console,这样日志就清爽多了。
  • 内存不足: 本地模式默认使用 1GB 内存。如果你的机器内存不大,启动时加上 --driver-memory 512m 限制一下,不然跑大一点的数据集可能会卡死。

好了,环境搭好了,第一个程序也跑通了。接下来你就可以放心大胆地折腾 Spark 了。记住,本地模式是你最好的朋友——快速验证、及时反馈,比在集群上反复提交作业高效得多。