环境搭建:Spark 与 Delta Lake 的版本兼容性、Maven/SBT 依赖配置、本地开发环境初始化
说实话,搞数据工程这么多年,我见过太多因为版本不匹配导致的诡异问题了。明明代码写得没问题,一跑就报错,查半天发现是 Spark 和 Delta Lake 版本没对齐。这一章咱们就把环境搭好,后面写代码才踏实。
版本兼容性:别在这上面翻车
Delta Lake 和 Spark 的版本关系,说白了就是「夫妻档」——得门当户对。我刚开始用 Delta Lake 时,图省事随便配了个版本,结果运行时各种 ClassNotFoundException,折腾了两天才发现是兼容性问题。
下面这张表是我整理的核心版本对应关系,建议你直接收藏:
| Delta Lake 版本 | Apache Spark 版本 | Scala 版本 | 备注 |
|---|---|---|---|
| 2.0.x | 3.2.x | 2.12 / 2.13 | 稳定版,推荐生产使用 |
| 2.1.x | 3.3.x | 2.12 / 2.13 | 支持新特性如 Change Data Feed |
| 2.2.x | 3.3.x | 2.12 / 2.13 | 修复了部分并发写入问题 |
| 2.3.x | 3.4.x | 2.12 / 2.13 | 最新稳定版,推荐新项目使用 |
| 1.x | 2.4.x - 3.1.x | 2.11 / 2.12 | 已停止维护,不建议新项目使用 |
Maven / SBT 依赖配置
依赖配置这块,我个人习惯用 Maven,但 SBT 也完全没问题。关键是选对 artifact 和版本号。
Maven 配置
在 pom.xml 里加上这段:
<!-- Spark 核心依赖 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.3.2</version>
<scope>provided</scope>
</dependency>
<!-- Delta Lake 核心依赖 -->
<dependency>
<groupId>io.delta</groupId>
<artifactId>delta-core_2.12</artifactId>
<version>2.1.0</version>
</dependency>
provided scope,因为运行时集群会提供 Spark 包。Delta Lake 则用默认 scope,确保打包时包含进去。
SBT 配置
如果你用 SBT,build.sbt 这样写:
name := "delta-lake-demo"
version := "1.0"
scalaVersion := "2.12.17"
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "3.3.2" % "provided",
"org.apache.spark" %% "spark-sql" % "3.3.2" % "provided",
"io.delta" %% "delta-core" % "2.1.0"
)
嗯,这里要注意 Scala 版本号必须和 Spark 编译用的 Scala 版本一致。你想想看,如果 Spark 是 2.12 编译的,你用了 2.13 的 Delta Lake,那肯定报错。
本地开发环境初始化
本地环境搭建,我建议用 IntelliJ IDEA + Maven 的组合。为什么?因为调试方便,依赖管理清晰。
第一步:创建项目结构
标准的 Maven 项目结构长这样:
delta-lake-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── scala/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── DeltaLakeApp.scala
│ │ └── resources/
│ │ └── log4j.properties
│ └── test/
│ └── scala/
└── data/
第二步:编写初始化代码
写一个简单的 SparkSession 初始化,验证环境是否正常:
import org.apache.spark.sql.SparkSession
object DeltaLakeApp {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
.appName("DeltaLakeDemo")
.master("local[*]")
.config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension")
.config("spark.sql.catalog.spark_catalog",
"org.apache.spark.sql.delta.catalog.DeltaCatalog")
.getOrCreate()
println("Spark Session 创建成功!")
println(s"Delta Lake 版本: ${spark.version}")
// 验证 Delta Lake 是否可用
try {
spark.sql("SELECT 1 AS test").show()
println("Delta Lake 环境初始化完成!")
} catch {
case e: Exception =>
println(s"环境初始化失败: ${e.getMessage}")
} finally {
spark.stop()
}
}
}
spark.sql.extensions:注册 Delta Lake 的 SQL 扩展spark.sql.catalog.spark_catalog:替换默认的 catalog 实现master("local[*]"):本地模式运行,使用所有可用核心
第三步:运行验证
在 IntelliJ 里直接运行 DeltaLakeApp,如果控制台输出:
Spark Session 创建成功!
Delta Lake 版本: 3.3.2
+----+
|test|
+----+
| 1|
+----+
Delta Lake 环境初始化完成!
那就说明环境搭好了。我曾经遇到过一个问题:明明依赖配对了,但运行时还是报 ClassNotFoundException: io.delta.sql.DeltaSparkSessionExtension。后来发现是 Maven 打包时没把 Delta Lake 的依赖打进去。解决办法是在 pom.xml 里加上 maven-assembly-plugin 或者用 sbt assembly。
核心架构图:环境搭建全景
下面这张图帮你理清整个环境搭建的脉络:
常见问题与避坑指南
- 版本不匹配:我曾经把 Delta Lake 2.0 和 Spark 3.1 搭在一起,结果事务日志写入就报错。解决办法就是严格按照上面的兼容表来配。
- 依赖冲突:项目中如果有其他 Spark 组件(如 Hive、Kafka),可能会和 Delta Lake 的依赖冲突。我建议用
mvn dependency:tree检查依赖树,排除冲突的包。 - 本地模式内存不足:默认的
local[*]会用所有核心,但内存可能不够。可以在 SparkSession 里加.config("spark.driver.memory", "4g")来调整。 - Windows 用户注意:如果你在 Windows 上开发,记得装 Hadoop 的 winutils.exe,不然会报
Failed to locate the winutils binary错误。我当年被这个坑了整整一下午。
- 检查 Spark 和 Delta Lake 版本是否匹配
- 确认 Maven/SBT 依赖配置正确
- 运行初始化代码,看是否报 ClassNotFoundException
- 执行一条简单的 SQL 查询,验证 Delta Lake 扩展是否生效
环境搭建这块,说白了就是「一次配置,长期受益」。花点时间把基础打牢,后面写业务逻辑时才不会因为环境问题分心。我个人习惯把这份配置模板保存下来,每次新项目直接复用,省时省力。