环境搭建与基础配置:Spark + Delta Lake 环境安装、配置Catalog、创建第一个Delta表
说实话,很多搞数据治理的人,一上来就谈元数据、谈血缘、谈策略。但在我看来,如果连环境都没搭利索,后面全是空中楼阁。这一章,我们就亲手把地基打牢。
我会带你走完三件事:装好 Spark + Delta Lake、配好 Catalog、然后创建你的第一个 Delta 表。嗯,每一步我都会穿插一些我在项目里踩过的坑,希望能帮你省点时间。
1. 环境选型:到底该用哪个版本?
先别急着敲命令。版本选不对,后面全是泪。我见过太多人因为版本不兼容,折腾一整天。
我个人习惯用这张表来快速决策:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| Apache Spark | 3.4.x 或 3.5.x | Delta Lake 对 3.x 支持最稳定 |
| Delta Lake | 2.4.x 或 3.0.x | 3.0 开始支持 Liquid Clustering |
| Scala | 2.12 或 2.13 | 跟 Spark 编译版本走 |
| Java | 8 或 11 | Spark 3.4+ 推荐 Java 11 |
| Hadoop | 3.3.x | 主要用它的文件系统 API |
delta-spark 依赖,而不是老的 delta-core。我曾经在升级时忽略了这一点,结果表都写不进去,排查了半天才发现是依赖名变了。
2. 安装方式:我推荐用 Maven 或 PyPI
搭建方式有很多种。本地开发我推荐两种:
- Java/Scala 项目:用 Maven 或 SBT 引入 Delta Lake 依赖
- Python 项目:直接用 pip 安装
delta-spark包
下面我分别给出示例。先看 Maven 的 pom.xml 片段:
<!-- Spark Core -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.5.0</version>
</dependency>
<!-- Spark SQL -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.5.0</version>
</dependency>
<!-- Delta Lake -->
<dependency>
<groupId>io.delta</groupId>
<artifactId>delta-spark_2.12</artifactId>
<version>3.0.0</version>
</dependency>
再看 Python 的安装方式,一行搞定:
pip install delta-spark==3.0.0 pyspark==3.5.0
3. 配置 Catalog:让 Spark 认识 Delta Lake
装好包只是第一步。你得告诉 Spark:「嘿,我要用 Delta Lake 的 Catalog 来管理表。」
这里有两种方式。第一种,在代码里用 config() 方法设置:
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("DeltaLakeDemo") \
.config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
.config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
.getOrCreate()
第二种,如果你用 spark-submit 提交任务,可以在命令行里加参数:
spark-submit \
--conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
--conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog" \
my_delta_job.py
为什么这两行配置这么重要?说白了,DeltaSparkSessionExtension 负责解析 Delta 相关的 SQL 语法,比如 DESCRIBE HISTORY、FSCK REPAIR TABLE。而 DeltaCatalog 则接管了 Spark 的元数据管理,让 Spark 知道去哪里找 Delta 表的 schema 和版本信息。
4. 创建第一个 Delta 表
环境配好了,我们来写点真东西。下面这段代码,会从 DataFrame 创建一个 Delta 表,并保存到本地文件系统。
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StructField, StringType, IntegerType, DoubleType
# 1. 创建 SparkSession(带上 Delta 配置)
spark = SparkSession.builder \
.appName("FirstDeltaTable") \
.config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
.config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
.getOrCreate()
# 2. 定义 Schema(我习惯显式定义,避免类型推断翻车)
schema = StructType([
StructField("order_id", StringType(), False),
StructField("customer_id", StringType(), True),
StructField("product", StringType(), True),
StructField("amount", DoubleType(), True),
StructField("order_date", StringType(), True)
])
# 3. 造一些示例数据
data = [
("ORD001", "C001", "笔记本电脑", 7999.00, "2024-01-15"),
("ORD002", "C002", "机械键盘", 899.00, "2024-01-16"),
("ORD003", "C001", "显示器", 2499.00, "2024-01-17")
]
# 4. 创建 DataFrame
df = spark.createDataFrame(data, schema)
# 5. 写入为 Delta 表
df.write \
.format("delta") \
.mode("overwrite") \
.save("/tmp/delta_orders")
# 6. 验证:读回来看看
spark.read.format("delta").load("/tmp/delta_orders").show()
执行成功后,你会看到类似这样的输出:
+--------+-----------+----------+------+----------+
|order_id|customer_id| product|amount|order_date|
+--------+-----------+----------+------+----------+
| ORD001| C001|笔记本电脑|7999.0|2024-01-15|
| ORD002| C002| 机械键盘| 899.0|2024-01-16|
| ORD003| C001| 显示器|2499.0|2024-01-17|
+--------+-----------+----------+------+----------+
表创建成功了。但你可能好奇:Delta 表到底长什么样?去 /tmp/delta_orders 目录下看看:
delta_orders/
├── _delta_log/ # 事务日志目录
│ └── 00000000000000000001.json
├── part-00000-xxx.snappy.parquet
├── part-00001-xxx.snappy.parquet
└── _committed_xxx
看到了吗?_delta_log 目录就是 Delta Lake 的灵魂。里面每个 JSON 文件记录了一次事务操作。你想想看,有了这个日志,Spark 就能知道这张表经历过哪些写入、删除、更新,甚至能回到任意历史版本。
5. 核心知识图谱:一张图看懂本章脉络
下面这张 SVG 图,把环境搭建到创建第一个 Delta 表的完整链路画了出来。你可以把它当作本章的「导航地图」。
6. 避坑指南:我踩过的几个坑
环境搭建看起来简单,但实际项目中总有些小陷阱。我挑三个最常见的说说:
- 依赖冲突:Spark 自带的 Jackson、Hadoop 版本,跟 Delta Lake 引入的版本打架。我曾经在集成测试时,一跑
save()就报NoSuchMethodError。解决办法是用 Maven 的<exclusions>排除冲突传递依赖。 - 路径权限:Delta 表写入时会创建
_delta_log目录。如果 HDFS 或 S3 的权限没配好,写事务日志那一步就会静默失败。我建议先手动touch一个文件测试权限。 - Catalog 没生效:有时候配置写对了,但 SparkSession 启动时没加载。一个快速验证方法是执行
spark.sql("SET spark.sql.catalog.spark_catalog"),看返回值是不是DeltaCatalog。
好了,环境搭好了,第一个 Delta 表也建起来了。你现在手里已经有了一个能跑 Delta Lake 的 Spark 环境,也亲眼看到了 _delta_log 目录长什么样。这些基础打牢了,后面讲事务、讲 Schema 演进、讲时间旅行,你才能真的理解它们在底层是怎么协作的。