
简介spark-3.2.0-bin-hadoop3.2.tgz 是 Apache Spark 3.2.0 面向 Hadoop 3.2 环境编译的官方二进制发行包适合大数据开发工程师、数据科学家及高校学生快速搭建分布式计算与机器学习实验环境。压缩包共 1476 个文件约 287.02MB以 462 个 py、238 个 jar、203 个 scala、135 个 java 等源码与依赖文件为主并含 91 个 txt 说明、32 个 sh 与 16 个 cmd 启动脚本以及 parquet、orc、avro 等示例数据文件覆盖 Spark Core、SQL、Streaming、MLlib、GraphX 全部核心组件。该版本在 DataFrame/Dataset 性能、Catalyst 优化器、PySpark 一致性、Kubernetes 原生支持及内存管理上均有改进并新增时间旅行查询等能力。解压后可直接在 Hadoop 3.2 集群运行 spark-submit、spark-shell 与 pyspark便于对照源码与脚本理解任务调度、SQL 执行及流处理机制。目前已有 1123 人学习下载适合需要完整发行包进行本地调试、集群部署与版本对比的读者。1. 拿到 spark-3.2.0-bin-hadoop3.2.tgz 之后它到底是什么能省掉哪些折腾如果你在搜索框里敲下spark-3.2.0-bin-hadoop3.2.tgz大概率不是想听 Spark 的发展史而是手里已经有一个 tgz 包或者正准备下载一个想知道它能不能直接跑、跟 Hadoop 怎么对接、解压完该改哪几个文件。这个包是 Apache Spark 官方发布的预编译二进制发行版版本号 3.2.0编译时绑定的 Hadoop 版本是 3.2。名字里的bin说明它已经帮你把 Scala、Java 依赖、启动脚本、示例 jar 全部打好了hadoop3.2说明它默认按 Hadoop 3.2 的客户端接口来编译连的是 Hadoop 3.x 的 HDFS 和 YARN。它解决的核心问题是你不需要自己装 Maven、不需要从源码编译、不需要折腾 Scala 版本对齐解压就能用spark-shell、spark-submit、pyspark。适合谁适合要搭本地开发环境的后端或数据开发、要跑课程设计的学生、要在伪分布式或集群上提交第一个 Spark 作业的人。不适合谁不适合已经用 Databricks 托管服务、或者需要 Spark 3.5 新特性的人。一句话这是「从零开始安装 Hadoop」之后最省事的那块拼图。2. 解压、环境变量与三种启动模式把 tgz 变成能跑的命令2.1 解压位置和目录结构决定了后面所有路径拿到 tgz 之后第一件事不是急着spark-shell而是选一个不会带空格、不会带中文的路径。Linux 下我一般放/opt/bigdata/Windows 下放D:\bigdata\。原因很简单Spark 的启动脚本里大量拼接路径空格会让classpath断掉中文在某些 locale 下会乱码。# Linux / macOS 下解压注意 -C 指定目标目录 mkdir -p /opt/bigdata tar -zxvf spark-3.2.0-bin-hadoop3.2.tgz -C /opt/bigdata/ # 进入目录看结构确认关键子目录都在 cd /opt/bigdata/spark-3.2.0-bin-hadoop3.2 ls -1 # bin/ 启动脚本spark-shell、spark-submit、pyspark # sbin/ 集群脚本start-master.sh、start-workers.sh # conf/ 配置文件spark-env.sh、spark-defaults.conf # jars/ 所有依赖 jarSpark 本体和 Hadoop 客户端都在这里 # examples/ 示例 jar用来验证环境 # python/ pyspark 的 Python 包逻辑说明bin/是给开发者用的sbin/是给集群管理员用的。jars/里已经包含了 Hadoop 3.2 的客户端 jar所以只要你连的 HDFS 是 3.x理论上不用额外拷 jar。参数说明-C指定解压目录-z表示 gzip-x解压-v显示过程-f指定文件。这四个参数顺序可以换但-f必须紧挨文件名。2.2 环境变量只配三个多配反而容易冲突很多人一上来就抄一堆SPARK_HOME、HADOOP_HOME、JAVA_HOME、SCALA_HOME结果spark-submit报No such file or directory。血泪经验是Spark 3.2 自带 Scala不需要你单独装 ScalaHadoop 客户端 jar 已经在jars/里不需要HADOOP_HOME也能跑本地模式。真正必须配的只有JAVA_HOME和SPARK_HOMEPATH里加上$SPARK_HOME/bin。# 编辑 ~/.bashrc 或 /etc/profile export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export SPARK_HOME/opt/bigdata/spark-3.2.0-bin-hadoop3.2 export PATH$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin # 让配置生效 source ~/.bashrc # 验证能打印版本就说明环境变量对了 spark-submit --version逻辑说明spark-submit --version会输出 Spark 版本、Scala 版本、Java 版本。如果这里报JAVA_HOME is not set说明 Java 路径写错了。参数说明Java 8 是 Spark 3.2 的推荐版本Java 11 也能跑但部分 API 有警告Java 17 不建议。SPARK_HOME不要带结尾斜杠脚本里会自己加。2.3 三种启动模式local、standalone、on YARN 怎么选Spark 3.2 的spark-submit支持多种 master URL新手最容易懵的是local[*]、spark://host:7077、yarn到底什么时候用哪个。master URL适用场景是否需要 Hadoop进程数local[2]本地开发、单元测试否单 JVM 内 2 线程local[*]本地跑小数据集否用满所有核spark://host:7077独立集群不依赖 YARN否Master Workeryarn已有 Hadoop 集群资源统一调度是YARN 分配常见做法是开发阶段用local[*]验证逻辑要连 HDFS 读数据时把fs.defaultFS指向你的 NameNode要提交到集群时再换成yarn。注意local[*]下sc.textFile(hdfs://...)也能跑因为 Spark 会直接用jars/里的 Hadoop 客户端去连不需要你启动 YARN。# 本地模式启动 spark-shell验证安装 spark-shell --master local[2] # 在 shell 里跑一行 WordCount确认能出结果 val rdd sc.parallelize(List(spark, hadoop, spark)) rdd.map((_, 1)).reduceByKey(_ _).collect() # 预期输出Array((spark,2), (hadoop,1))逻辑说明sc是 SparkContextspark-shell启动时自动创建。parallelize把本地集合转成 RDDreduceByKey做聚合。参数说明local[2]表示用 2 个线程写local[*]会用满 CPU 核数。这一步能跑通说明 tgz 包本身没问题后面连不上 HDFS 就是 Hadoop 侧的事。3. 连 HDFS 与提交 YARN配置文件改哪几行参数怎么对齐3.1 让 Spark 找到 HDFScore-site.xml 的两种放法Spark 读 HDFS 靠的是 Hadoop 客户端配置。spark-3.2.0-bin-hadoop3.2.tgz的jars/里已经有hadoop-client相关 jar但默认不知道你的 NameNode 地址。两种做法一是把 Hadoop 的core-site.xml和hdfs-site.xml拷到$SPARK_HOME/conf/二是直接在spark-defaults.conf里写spark.hadoop.fs.defaultFS。我一般用第一种因为跟 Hadoop 命令行行为一致排查时少一个变量。# 假设 Hadoop 装在 /opt/bigdata/hadoop-3.2.1 cp /opt/bigdata/hadoop-3.2.1/etc/hadoop/core-site.xml $SPARK_HOME/conf/ cp /opt/bigdata/hadoop-3.2.1/etc/hadoop/hdfs-site.xml $SPARK_HOME/conf/ # 确认 core-site.xml 里的 fs.defaultFS 指向你的 NameNode grep -A1 fs.defaultFS $SPARK_HOME/conf/core-site.xml # 常见值hdfs://localhost:9000 或 hdfs://namenode-host:8020逻辑说明Spark 启动时会自动加载conf/下的core-site.xml所以拷过来就能生效。参数说明fs.defaultFS的端口取决于 Hadoop 配置伪分布式常见 9000 或 8020集群模式看core-site.xml实际值。如果这里写错spark-shell里执行sc.textFile(hdfs:///tmp/test.txt)会报Connection refused。# 验证在 spark-shell 里读 HDFS 文件 spark-shell --master local[2] val data sc.textFile(hdfs://localhost:9000/tmp/wordcount.txt) data.count() # 能返回行数说明 HDFS 连通逻辑说明textFile返回 RDD[String]count()触发实际读取。如果报FileNotFoundException说明路径不对报Connection refused说明 NameNode 地址或端口不对。注意 HDFS 上文件路径要写全/tmp/wordcount.txt前面要加hdfs://localhost:9000。3.2 提交到 YARNspark-submit 的五个关键参数当你要把作业扔到已有 Hadoop 集群上跑--master yarn是入口但真正决定成败的是--deploy-mode、--executor-memory、--executor-cores、--num-executors、--queue这几个。Hadoop 作业提交到 YARN 的流程里Spark 会先申请一个 ApplicationMaster 容器再由 AM 去申请 Executor 容器。# 提交一个 Spark 作业到 YARNclient 模式便于看日志 spark-submit \ --master yarn \ --deploy-mode client \ --executor-memory 2g \ --executor-cores 2 \ --num-executors 4 \ --queue default \ --class org.apache.spark.examples.SparkPi \ $SPARK_HOME/examples/jars/spark-examples_2.12-3.2.0.jar \ 100逻辑说明--class指定主类最后两个参数是 jar 路径和传给 main 的参数。--deploy-mode client下 Driver 跑在你提交命令的机器上日志直接打印在终端适合调试cluster模式下 Driver 跑在 YARN 容器里终端看不到日志要用yarn logs -applicationId查。参数说明--executor-memory 2g是每个 Executor 的内存--executor-cores 2是每个 Executor 的核数--num-executors 4是 Executor 总数。总资源 4 * 2g 内存 4 * 2 核要小于队列可用资源否则会卡在ACCEPTED状态。注意--num-executors在--deploy-mode client下由spark-submit直接传给 YARN但在某些 Hadoop 版本里会被spark.dynamicAllocation覆盖。如果发现 Executor 数量不对先检查spark-defaults.conf里有没有开启动态分配。3.3 读 JSON 和写 ParquetSpark 3.2 里最常用的两个数据入口Spark 数据分析案例里读 JSON 和写 Parquet 几乎是标配。Spark 3.2 的spark.read.json支持多行 JSON但默认只认单行一条记录。如果你的 JSON 文件是格式化过的多行结构要加multiLinetrue。# pyspark 读 JSON注意 multiLine 参数 from pyspark.sql import SparkSession spark SparkSession.builder \ .appName(json-demo) \ .master(local[2]) \ .getOrCreate() # 单行 JSON直接读 df spark.read.json(hdfs://localhost:9000/tmp/users.json) df.printSchema() df.show(5) # 多行 JSON必须加 option df_multi spark.read.option(multiLine, true).json(hdfs://localhost:9000/tmp/nested.json) # 写成 Parquet压缩用 snappy df.write.mode(overwrite).parquet(hdfs://localhost:9000/tmp/users_parquet)逻辑说明printSchema()打印推断出的 schemashow(5)显示前 5 行。multiLinetrue会让 Spark 先读整个文件再解析大文件慎用容易 OOM。参数说明mode(overwrite)覆盖已有目录mode(append)追加。Parquet 默认压缩是 snappy如果集群没装 snappy 本地库会报native snappy library not available这时可以换gzip或none。# 如果 snappy 报错改用 gzip df.write.mode(overwrite).option(compression, gzip).parquet(hdfs://localhost:9000/tmp/users_parquet_gz)逻辑说明option(compression, gzip)在写 Parquet 时生效。参数说明gzip 压缩率高但读写慢snappy 平衡最好lz4 更快但压缩率低。生产环境一般用 snappy本地测试没装 native 库时用 gzip 绕过。4. 避坑与排查tgz 包跑不起来时先看这五条4.1 现象spark-shell启动报JAVA_HOME is not set原因spark-env.sh或系统环境变量里JAVA_HOME没配或者配了但路径指向 JRE 而不是 JDK。Spark 需要 JDK 里的tools.jarJava 8或jdk.compiler模块Java 11。解决确认echo $JAVA_HOME输出的是 JDK 根目录且$JAVA_HOME/bin/javac存在。如果用的是 Java 11Spark 3.2 能跑但会有Illegal reflective access警告不影响功能。Java 17 需要加--add-opens参数不建议新手折腾。4.2 现象连 HDFS 报Connection refused或UnknownHostException原因core-site.xml里的fs.defaultFS写的是主机名但本机/etc/hosts没解析或者 NameNode 根本没启动。解决先用hdfs dfs -ls /确认 Hadoop 自己能连上。如果 Hadoop 命令能连、Spark 连不上检查$SPARK_HOME/conf/下有没有core-site.xml。如果报UnknownHostException在/etc/hosts里加一行127.0.0.1 namenode-host。4.3 现象提交 YARN 后一直卡在ACCEPTED不变成RUNNING原因YARN 队列资源不足或者--executor-memory加--executor-cores算出来的总资源超过了队列上限。常见于--num-executors设太大。解决用yarn application -list看应用状态用yarn queue -status default看队列资源。先把--num-executors降到 1、--executor-memory降到 1g 试跑能跑通再往上加。注意spark.yarn.am.memory默认 1g如果 AM 都申请不到会直接失败。4.4 现象读 JSON 报Failed to read data或 schema 全变成 string原因JSON 文件里有格式不一致的行或者multiLine没开。Spark 的 schema 推断会扫描一部分数据如果样本里某字段全是 null推断出来就是 string。解决先df.printSchema()看推断结果如果不对手动指定 schema。用spark.read.schema(customSchema).json(...)跳过推断。对于多行 JSON加option(multiLine, true)但注意大文件会内存溢出。4.5 现象写 Parquet 报native snappy library not available原因spark-3.2.0-bin-hadoop3.2.tgz自带的 snappy 是 Java 实现但某些操作会尝试加载 native 库。在 Windows 或精简版 Linux 上容易触发。解决写的时候显式指定option(compression, gzip)或option(compression, none)。如果一定要 snappy在spark-defaults.conf里加spark.sql.parquet.compression.codecgzip全局改掉。这个坑在课程设计里很常见因为学生机往往没装libsnappy。5. 进阶技巧用 spark-submit 的 --files 和 --jars 把依赖带进集群5.1 为什么需要 --files 和 --jars本地跑得好好的作业一提交到 YARN 就报ClassNotFoundException或FileNotFoundException八成是依赖没带上去。spark-submit的--jars把额外 jar 分发到每个 Executor 的 classpath--files把配置文件、字典文件分发到每个 Executor 的工作目录。这两个参数是 Spark 作业从「本地能跑」到「集群能跑」的关键一步。# 提交时带上自定义 jar 和配置文件 spark-submit \ --master yarn \ --deploy-mode cluster \ --jars /opt/libs/mysql-connector-java-8.0.28.jar,/opt/libs/fastjson-1.2.79.jar \ --files /opt/conf/app.properties,/opt/data/dict.txt \ --executor-memory 4g \ --executor-cores 2 \ --num-executors 8 \ --class com.example.MainJob \ /opt/jobs/my-spark-job.jar \ --input hdfs://localhost:9000/tmp/input \ --output hdfs://localhost:9000/tmp/output逻辑说明--jars里的 jar 会被复制到每个 Executor 的$PWD下并加入 classpath。--files里的文件会被复制到每个 Executor 的工作目录代码里用new File(app.properties)就能读到不需要写绝对路径。参数说明多个 jar 用逗号分隔不要有空格。--files同理。注意--jars里的 jar 如果跟 Spark 自带 jar 冲突会优先用--jars里的这可能导致版本问题。5.2 在代码里读取 --files 分发的文件# pyspark 里读取 --files 分发的配置文件 from pyspark import SparkFiles # 方式一通过 SparkFiles.get 拿绝对路径 config_path SparkFiles.get(app.properties) with open(config_path) as f: content f.read() # 方式二直接在当前工作目录找Executor 的 CWD 就是分发目录 import os if os.path.exists(dict.txt): with open(dict.txt) as f: dict_data f.read().splitlines()逻辑说明SparkFiles.get(app.properties)返回该文件在 Executor 上的绝对路径Driver 和 Executor 都能用。方式二依赖 Executor 的 CWD在cluster模式下更可靠。参数说明--files分发的文件默认不覆盖同名文件如果 Executor 上已有同名文件行为取决于 Spark 版本3.2 里会覆盖。5.3 验证依赖是否真的分发成功提交之后不要只看ApplicationMaster状态要进 Executor 日志确认。用yarn logs -applicationId application_xxx拉日志搜app.properties或mysql-connector。如果日志里报FileNotFoundException: app.properties说明--files没生效检查路径是不是绝对路径、文件是不是存在。# 拉取 YARN 应用日志过滤关键信息 yarn logs -applicationId application_1680000000000_0001 | grep -E app.properties|mysql-connector|ClassNotFoundException逻辑说明yarn logs会把 AM 和所有 Executor 的日志合并输出grep过滤出跟依赖相关的行。参数说明applicationId从yarn application -list里拿。如果日志太大可以加-log_files指定只拉某个容器的日志。从那以后我每次提交集群作业前都强制走一遍「本地local[2]跑通 → 带--jars和--files提交yarn client→ 确认日志无ClassNotFoundException→ 再换cluster模式」这个流程。多花五分钟省掉半夜被电话叫醒查 YARN 日志的麻烦。希望帮到你。本文还有配套的精品资源点击获取